I'm interested if there is any way to set an attribute on the Pydantic Model class the will only be used when constructing the output representation of the object. Something that works like Django Rest Framework SerializerMethodField. It is highly useful when you need to construct output depending on the environment or many other conditions.
Asked
Active
Viewed 666 times
3
-
https://stackoverflow.com/questions/63264888/pydantic-using-property-getter-decorator-for-a-field-with-an-alias sounds similar – Drdilyor May 28 '21 at 04:23
-
The problem with the solution outlined in @Drdilyor linked answer is that it assumes that the "SerializerMethod" method will only use values from the pydantic model. It cannot use fields from the ORM class that are not part of the Pydantic model. – Martin Faucheux Feb 15 '23 at 16:28
2 Answers
0
It's possible to have a similar mechanism as django's SerializerMethodField by overriding pydantic BaseModel class
from copy import deepcopy
from pydantic import BaseModel, Field
class Person:
def __init__(self, name, likes_cake):
self.name = name
self.likes_cake = likes_cake
class CustomPydanticModel(BaseModel):
@classmethod
def from_orm(cls, obj, getter_binding=None):
getter_binding = getter_binding or {}
obj = deepcopy(obj)
for field in cls.__fields__:
method = getter_binding.get(field)
if method is None:
method = getattr(cls, f"get_{field}", None)
if method is not None and callable(method):
setattr(obj, field, method(obj))
return super().from_orm(obj)
class PersonModel(CustomPydanticModel):
name: str
status: str | None = None
@staticmethod
def get_status(obj):
return "I like cake" if obj.likes_cake else "Hello"
class Config:
orm_mode = True
obj = Person("Patrick", True)
pydantic_obj = PersonModel.from_orm(obj)
Note that the get_status method should be static or classmethod

Martin Faucheux
- 884
- 9
- 26
0
Had the same problem, solved it using @root_validator. Check my example:
class HireCandidateResponse(BaseModel):
Id: str
VacancyId: str
Data: HireCandidateData
hire_request_title: Optional[str]
@root_validator
def populate_hire_request_title(cls, values):
vacancy_title = (
values['Data'].ProfileId.Name if values['Data'] and values['Data'].ProfileId and values['Data'].ProfileId.Name else ''
)
org_unit_title = (
values['Data'].OrgUnitId.Name if values['Data'] and values['Data'].OrgUnitId and values['Data'].OrgUnitId.Name else ''
)
values['hire_request_title'] = f'{vacancy_title} {org_unit_title}'
return values

Artem Chege
- 189
- 2
- 5