Reputation: 2095
this is my database schema.
I defined my Schema like this:
from pydantic import BaseModel
class Userattribute(BaseModel):
name: str
value: str
user_id: str
id: str
This is my model:
class Userattribute(Base):
__tablename__ = "user_attribute"
name = Column(String)
value = Column(String)
user_id = Column(String)
id = Column(String, primary_key=True, index=True)
In a crud.py I define a get_attributes
method.
def get_attributes(db: Session, skip: int = 0, limit: int = 100):
return db.query(models.Userattribute).offset(skip).limit(limit).all()
This is my GET
endpoint:
@app.get("/attributes/", response_model=List[schemas.Userattribute])
def read_attributes(skip: int = 0, limit: int = 100, db: Session = Depends(get_db)):
users = crud.get_attributes(db, skip=skip, limit=limit)
print(users)
return users
The connection to the database seems to work, but a problem is the datatype:
pydantic.error_wrappers.ValidationError: 7 validation errors for Userattribute
response -> 0
value is not a valid dict (type=type_error.dict)
response -> 1
value is not a valid dict (type=type_error.dict)
response -> 2
value is not a valid dict (type=type_error.dict)
response -> 3
value is not a valid dict (type=type_error.dict)
response -> 4
value is not a valid dict (type=type_error.dict)
response -> 5
value is not a valid dict (type=type_error.dict)
response -> 6
value is not a valid dict (type=type_error.dict)
Why does FASTApi expect a dictionary here? I don´t really understand it, since I am not able to even print the response. How can I fix this?
Upvotes: 34
Views: 60765
Reputation: 52892
Pydantic 2 changed how models gets configured, so if you're using the most recent version of Pydantic, see the section named Pydantic 2 below.
SQLAlchemy does not return a dictionary, which is what pydantic expects by default. You can configure your model to also support loading from standard orm parameters (i.e. attributes on the object instead of dictionary lookups):
class Userattribute(BaseModel):
name: str
value: str
user_id: str
id: str
class Config:
orm_mode = True
You can also attach a debugger right before the call to return
to see what's being returned.
Since this answer has become slightly popular, I'd like to also mention that you can make orm_mode = True
the default for your schema classes by having a common parent class that inherits from BaseModel
:
class OurBaseModel(BaseModel):
class Config:
orm_mode = True
class Userattribute(OurBaseModel):
name: str
value: str
user_id: str
id: str
This is useful if you want to support orm_mode
for most of your classes (and for those where you don't, inherit from the regular BaseModel
).
Pydantic 2
Pydantic 2 has replaced the internal Config
class with a model_config
field:
from pydantic import ConfigDict
class OurBaseModel(BaseModel):
model_config = ConfigDict(from_attributes=True)
This works in the same way as the old orm_mode
.
Upvotes: 81
Reputation: 345
This error is caused by two things:
The reponse_model parameter in the path operation decorator, which defines the type/shape of response to be returned. Removing this will eliminate the errors you see, as it will remove the validation against what is being returned.
The internal Config class that is missing in your Pydantic schemas.
Make sure to add the Config class to avoid this problem, or at worst, remove the response_model parameter (which I doubt anyone would consider). Example is:
class ItemBase(BaseModel):
title: str
description: Union[str, None] = None
class Config:
orm_mode = True
Adding this class allows Pydantic model to read data in non-dictionary format, thereby allowing you to return database model.
Checkout the fastAPI documentation for more
Upvotes: 1