Reputation: 678
I am writing a FastAPI application, and have the need to essentially merge some properties from two SQLAlchemy model instances into a single Pydantic model for the response, some properties from Object A and some from Object B, returning a "consolidated" object.
class Message:
id = Column(Integer, primary_key=True)
subject = Column(Text)
message = Column(Text)
class FolderLink:
id = Column(Integer, primary_key=True)
message_id = Column(Integer, ForeignKey('message.id'))
folder_id = Column(Integer, ForeignKey('folder.id'))
is_read = Column(Boolean, nullable=False, default=False)
In application code, I have a Message
instance, needing all properties, and the relevant FolderLink
instance, from which I need is_read
.
My Pydantic schema looks like:
class MessageWithProperties(BaseModel):
id: int # from Message
subject: str # from Message
message: str # from Message
is_read: bool # from FolderLink
And in the view code, the only way I can seem to properly pass objects to the Pydantic model is like so:
objs = []
# [...]
for link in links:
objs.append({**link.message.__dict__, **link.__dict__})
It feels wrong to have to use a dunder method this way. I had experimented with a custom @classmethod constructor on the Pydantic model, but that will not work as I am not directly instantiating them myself, they are instantiated by FastAPI as part of the response handling.
What is the proper way to do this?
Upvotes: 0
Views: 3329
Reputation: 311238
What if instead of mashing all the fields togther you create a top level MessageWithProperties
class that is built from two inferior Pydantic models, one for Message
and one for FolderLink
? Something like:
class BaseSchema(pydantic.BaseModel):
class Config:
orm_mode = True
class MessageSchema(BaseSchema):
id: int # from Message
subject: str # from Message
message: str # from Message
class FolderLinkSchema(BaseSchema):
is_read: bool # from FolderLink
class CombinedSchema(BaseSchema):
message: MessageSchema
folderlink: FolderLinkSchema
objs = []
for link in links:
objs.append(CombinedSchema(
message=MessageSchema.from_orm(link.message),
folderlink=FolderLinkSchema.from_orm(link),
))
Now you'll be able to access both the FolderLink
and Message
attributes from each object in your objs
array.
Upvotes: 1