Reputation: 21
I'm working with Tortoise ORM in a FastAPI project and have a Channel
model which optionally includes a password hash when channel is protected. I want to generate a list of channels for API responses, where I exclude the password_hash
field and include a new computed boolean field, protected
, to indicate whether a channel is password protected.
Here's the model definition:
from tortoise import fields, models
from tortoise.contrib.pydantic import pydantic_model_creator
class Channel(models.Model):
id = fields.IntField(pk=True)
name = fields.CharField(max_length=100)
password_hash = fields.CharField(max_length=128, null=True)
owner = fields.ForeignKeyField('models.User', related_name='channels')
ChannelSchema = pydantic_model_creator(Channel, name="Channel")
Current API response example:
[
{
"id": 1,
"name": "my channel",
"password_hash": null
},
{
"id": 2,
"name": "my protected channel",
"password_hash": "$2b$..."
}
]
Desired API response:
[
{
"id": 1,
"name": "my channel",
"protected": false
},
{
"id": 2,
"name": "my protected channel",
"protected": true
}
]
How can I correctly include the protected
computed attribute in my Pydantic model while excluding the password_hash
field?
I attempted to create a computed attribute password_protected
and exclude password_hash
like so:
class Channel(models.Model):
...
def password_protected(self) -> bool:
return bool(self.password_hash)
class PydanticMeta:
computed = ["password_protected"]
# exclude = ["password_hash"]
However, excluding password_hash
leads to an error:
AttributeError: 'ResponseChannelSchema' object has no attribute 'password_hash'
Upvotes: 1
Views: 425
Reputation: 21
Here's how I solved this problem, using the serialize_password
method for serialization, and serialization_alias
.
class ResponseChannelSchema(ChannelSchema):
password_hash: str | None = Field(None, serialization_alias="protected")
@field_serializer('password_hash')
def serialize_password(self, v: str) -> bool:
return bool(v)
Upvotes: 1