You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
CRUD Sqlalchemy ORM, Pydantic and query on multiple table (like join table) #140
changed the title [-]CRUD Sqlalchemy ORM, Pydantic and query on multiple table[/-][+]CRUD Sqlalchemy ORM, Pydantic and query on multiple table (like join table)[/+]on Apr 8, 2020
You can't simply add a user_email field to that schema and expect it to be populated. Rather,
you need to also create a User schema. Otherwise Pydantic won't now how to connect the two models.
classUser(BaseModel):
classConfig:
orm_mode=Trueid: stremail: strhashed_password: strclassShiftDetailBase(BaseModel)
# add field for the owner (reference User model)# I believe you can remove the owner_id fieldowner: User
If you want user_email to be returned from that schema you would need to alter the design of your DB or I believe it might be possible with a custom Pydantic root validator - but that's making things more complex and breaks from the ORM model.
Reacted by Dat Pham Tat, Sebastián Ramírez, Francisco Hinojosa Luna and David Velásquez
And i dont know to to make data include Owner data ...
Normaly, i get list Shiftdetail, list User ; For LIST and mapping Owner_id with user.id in User; Return new list as expected
Is that best way to do in FastAPI. I dont think so :(
@tatdatpham First make sure that your SQLAlchemy query is returning the data that you want. Run that code outside of your FastAPI app and make sure it works.
Then, after you have your data, you have to convert it to have the shape of the model that you want to return. So, probably iterating in each of the rows in the result and putting all that in dicts, or something similar.
Then with that you can finally try to put it in a Pydantic model and see where the error is.
But first you have to debug the initial part and make sure that you are getting the data that you need, and then that you are converting it to the shape that you need.
As tiangolo said, verify you are returning the data you want (you should be). Your query should already be returning the data you need via SQLAlchemy here:
It will be nested, and not inline like you expected - I didn't like how this returns but just means dealing with it differently when consuming.
To improve and only provide what you need, create an additional schema def in the users_schema.py (or what you have named it...) such as:
class UserShared(BaseModel):
email: str
class Config:
orm_mode = True
import that in your Shiftdetail.py and use it in the schema in place of "User" :
# Additional properties to return via API
class ShiftDetail(ShiftDetailBaseInDB):
create_time: datetime
owner: UserShared
class Config:
orm_mode = True
Then it will just return the email, and not all the user fields.
As tiangolo said, verify you are returning the data you want (you should be). Your query should already be returning the data you need via SQLAlchemy here:
It will be nested, and not inline like you expected - I didn't like how this returns but just means dealing with it differently when consuming.
To improve and only provide what you need, create an additional schema def in the users_schema.py (or what you have named it...) such as:
class UserShared(BaseModel):
email: str
class Config:
orm_mode = True
import that in your Shiftdetail.py and use it in the schema in place of "User" :
# Additional properties to return via API
class ShiftDetail(ShiftDetailBaseInDB):
create_time: datetime
owner: UserShared
class Config:
orm_mode = True
Then it will just return the email, and not all the user fields.
Weird... I've done exactly what you say here for my model, but I'm still getting field required (type=value_error.missing) errors
class InputTemplateShared(InputTemplateBase):
name: str
class Config:
orm_mode = True
# Shared Properties to return via API
class MetricShared(MetricBase):
name: str
class Config:
orm_mode: True
Both imported into input_template_base.py schema file where I have:
# Properties shared by models stored in DB
class InputTemplateDetailInDBBase(InputTemplateDetailBase):
template_id: Optional[int] = None
metric_id: Optional[int] = None
class Config:
orm_mode = True
# Properties to return to client
class InputTemplateDetail(InputTemplateDetailInDBBase):
template_name: InputTemplateShared
metric_name: MetricShared
class Config:
orm_mode = True
Have checked my db query and it's returning the correct orm object and I can access those fields...
I tried that approach but it still gives me pydantic errors (field missing).
When I get the InputTemplateDetail object back from the DB I need to access template name via: InputTemplateDetail.templates.name - does that make any difference to your answer?
How do I access that property here?
class InputTemplateDetail(InputTemplateDetailInDBBase):
template_name: str
class Config:
orm_mode = True
Activity
[-]CRUD Sqlalchemy ORM , query on multiple table[/-][+]CRUD Sqlalchemy ORM, Pydantic and query on multiple table[/+][-]CRUD Sqlalchemy ORM, Pydantic and query on multiple table[/-][+]CRUD Sqlalchemy ORM, Pydantic and query on multiple table (like join table)[/+]paul121 commentedon Apr 8, 2020
You can't simply add a
user_emailfield to that schema and expect it to be populated. Rather,you need to also create a User schema. Otherwise Pydantic won't now how to connect the two models.
The response would then look like:
If you want
user_emailto be returned from that schema you would need to alter the design of your DB or I believe it might be possible with a custom Pydantic root validator - but that's making things more complex and breaks from the ORM model.tatdatpham commentedon Apr 8, 2020
@paul121 . Sure, thank for your guide about schema. But i very confuse about making CRUD to return data that i need.
I have some code to return list of ShiftDetail (not include Owner)
And i dont know to to make data include Owner data ...
Normaly, i get list Shiftdetail, list User ; For LIST and mapping Owner_id with user.id in User; Return new list as expected
Is that best way to do in FastAPI. I dont think so :(
paul121 commentedon Apr 9, 2020
Can we think about the query in the reverse direction? This should return only the ShiftDetails that belong to one user. (not tested) ... eg:
tatdatpham commentedon Apr 10, 2020
Just query on one table only and model User dont have shiftdetails. It doesn't work :'(
paul121 commentedon Apr 11, 2020
hmm, sorry that didn't work @tatdatpham!☹️ I'm not sure what might be the issue. This likely isn't an issue with FastAPI, though
tiangolo commentedon Apr 13, 2020
Thanks for the help here @paul121 ! 👏 🍰
@tatdatpham First make sure that your SQLAlchemy query is returning the data that you want. Run that code outside of your FastAPI app and make sure it works.
If you need to understand better how to use SQLAlchemy, check the tutorial: https://docs.sqlalchemy.org/en/13/orm/tutorial.html
Then, after you have your data, you have to convert it to have the shape of the model that you want to return. So, probably iterating in each of the rows in the result and putting all that in
dicts, or something similar.Then with that you can finally try to put it in a Pydantic model and see where the error is.
But first you have to debug the initial part and make sure that you are getting the data that you need, and then that you are converting it to the shape that you need.
wedwardbeck commentedon Apr 21, 2020
As tiangolo said, verify you are returning the data you want (you should be). Your query should already be returning the data you need via SQLAlchemy here:
then add to your schema like so:
and then be sure to import the User Schema from where you defined that (.user for example).
This will return the data as shown in paul121's comments:
It will be nested, and not inline like you expected - I didn't like how this returns but just means dealing with it differently when consuming.
To improve and only provide what you need, create an additional schema def in the users_schema.py (or what you have named it...) such as:
import that in your Shiftdetail.py and use it in the schema in place of "User" :
Then it will just return the email, and not all the user fields.
SurelyYouareJoking commentedon May 10, 2020
Cozmo25 commentedon Jun 5, 2020
Weird... I've done exactly what you say here for my model, but I'm still getting
field required (type=value_error.missing)errorsBoth imported into input_template_base.py schema file where I have:
Have checked my db query and it's returning the correct orm object and I can access those fields...
Any ideas?
tiangolo commentedon Jun 12, 2020
@Cozmo25 I'm not sure I'm following correctly, but I think that by having something like:
And then, before that:
It would expect something like:
{ "template_name": { "name": "anode_graphite" } }Notice the nested
dictfortemplate_name.Could that be the problem?
Cozmo25 commentedon Jun 14, 2020
@tiangolo Thank you for the response much appreciated.
It’s very likely the problem, I’m just not sure how to create the structure I need (not nested instead of nested) where I have a join between tables.
tiangolo commentedon Jun 17, 2020
@Cozmo25 I think that instead of:
something like this could work:
Cozmo25 commentedon Jun 23, 2020
Thanks for this @tiangolo.
I tried that approach but it still gives me pydantic errors (field missing).
When I get the InputTemplateDetail object back from the DB I need to access template name via:
InputTemplateDetail.templates.name- does that make any difference to your answer?How do I access that property here?
adriendod commentedon Oct 23, 2021
hi @Cozmo25, have you succeeded to get the data inline instead of nested?
AthreyVinay commentedon Apr 14, 2022
Hi @adriendod Did you manage to get it inline?
AthreyVinay commentedon Apr 14, 2022
@wedwardbeck Your response works but it returns a nested response and not inline.... as in
{ "owner": { "email_address": "xyz@gmail.com" } }Anyway it can only return
Thanks
ryba147 commentedon Oct 9, 2022
@AthreyVinay hi! How did you manage to get it inline
"email_address": "xyz@gmail.com", but not nested:💚 Only run the backend service in tests (#140)