This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Is it possible to load sqlalchemy relationship fields conditionally? #2010
Comments
@ArcLightSlavik thanks, but I don't see how dependency injections could help in my case, could you elaborate, please ? |
It seems that my issue is an inverse of #194, old relationship properties behavior described there is what I'm trying to achieve. |
I think I found an ok solution using a custom GetterDict, here's what I came up with: from typing import Any
from pydantic import BaseModel
from pydantic.utils import GetterDict
import sqlalchemy
class IgnoreLazyGetterDict(GetterDict):
def __getitem__(self, key: str) -> Any:
try:
if self._is_lazy_loaded(key):
return None
return getattr(self._obj, key)
except AttributeError as e:
raise KeyError(key) from e
def get(self, key: Any, default: Any = None) -> Any:
# if a relationship field is not already loaded as a result of explicit join, ignore it,
# so that pydantic schema doesn't trigger a lazy-load
if self._is_lazy_loaded(key):
return None
return getattr(self._obj, key, default)
def _is_lazy_loaded(self, key: Any) -> bool:
return key in sqlalchemy.orm.attributes.instance_state(self._obj).unloaded
# a model to be used with sqlalchemy orm instances. It won't trigger lazy-load of relationship properties
class IgnoreLazyBaseModel(BaseModel):
class Config:
orm_mode = True
getter_dict = IgnoreLazyGetterDict |
Thanks for the help here @ArcLightSlavik ! ☕ I'm glad you found a solution @citizen4371 ! If that works for you, then you can close the issue. 🚀 In any case, you could also return Pydantic models directly. So, you could have 2 Pydantic models, one with the relationships and one without them. And then create the models in your code and return them. Or you could also extract the data that you are sure you want to return in a dictionary or list of dictionaries, and return that. |
I found that the above solution wasn't being applied to only relationships. This caused pydantic's orm_mode to fail. Below is the fix I came up with to use relationships only.
|
This issue was moved to a discussion.
You can continue the conversation there. Go to discussion →
Hi everybody, I've got the following question:
Let's say I have an sqlalchemy class, a Post that has a one-to-one relation to Author, corresponding Pydantic schemas, and an endpoint:
Currently FastApi tries to load every field from the pydantic schema, which leads to author field in the example above to be lazy loaded for every post item. Is there a way to stop FastApi from loading relationship fields, so that the only scenario in which these fields are present in the response would be the case in which an explicit join is made prior to orm instance being processed by FastApi ? I would make the join conditionally, based on some query parameter:
Environment
The text was updated successfully, but these errors were encountered: