In the code below, I'm creating an api that would accept a notification that should send an email. There are fields I want to add to the notification like an ID and TS after its been submitted. I have modeled it like below.
class NotificationPriority(Enum):
high = "high"
medium = "medium"
low = "low"
class Notification(BaseModel):
notification: str
priority: NotificationPriority
notification_from: str
class EmailNotification(Notification):
email_to: str
email_from: str | None = None
class EmailNotificationSystem(EmailNotification):
id: uuid.UUID = uuid.uuid4()
ts: datetime.datetime = datetime.datetime.now(datetime.UTC).isoformat()
email: EmailNotification
@app.post("/notifications/email")
async def create_notification(email_notification: EmailNotification):
print(email_notification.model_dump())
system = EmailNotificationSystem(
email=email_notification,
)
return system
Pydantic fails saying all the fields inside the email_notification that I'm setting with email=email_notification
are missing.
Field required [type=missing, input_value={'email': EmailNotificati...rom='namec@ccsmed.com')}, input_type=dict] For further information visit https://errors.pydantic.dev/2.7/v/missing priority Field required [type=missing, input_value={'email': EmailNotificati...rom='namec@ccsmed.com')}, input_type=dict] For further information visit https://errors.pydantic.dev/2.7/v/missing notification_from Field required [type=missing, input_value={'email': EmailNotificati...rom='namec@ccsmed.com')}, input_type=dict] For further information visit https://errors.pydantic.dev/2.7/v/missing email_to Field required [type=missing, input_value={'email': EmailNotificati...rom='namec@ccsmed.com')}, input_type=dict] For further information visit https://errors.pydantic.dev/2.7/v/missing
when I print(email_notification.model_dump())
I can see the fields are in there and satisfied. The request body looks like this:
{
"notification": "new notification",
"priority": "low",
"notification_from": "sampleapp",
"email_to":"nameb@ccsmed.com;nameb@ccsmed.com",
"email_from":"namec@ccsmed.com"
}
Primary Q: Why is it saying I'm missing fields?
Secondary Q: Is there a better practice to doing what I'm doing?
As masklin pointed out in the comment, EmailNotificationSystem
extends EmailNotification
, but also has it as a member. This probably isn't what you want here.
Another thing that's bad is the way you set the id
and ts
members. If you don't pass these in your JSON, they will always use the same default value, regardless of the time the notification was received. You should use Field
with the default_factory
parameter for this.
Here's a fixed version, based on the model dump you provided:
from datetime import datetime, UTC
from enum import Enum
from uuid import uuid4, UUID
from pydantic import BaseModel, Field
class NotificationPriority(Enum):
high = "high"
medium = "medium"
low = "low"
class Notification(BaseModel):
notification: str
priority: NotificationPriority
notification_from: str
class EmailNotification(Notification):
email_to: str
email_from: str | None = None
class EmailNotificationSystem(EmailNotification):
id: UUID = Field(default_factory=uuid4)
ts: datetime = Field(default_factory=lambda: datetime.now(UTC))
if __name__ == '__main__':
json_data = """
{
"notification": "new notification",
"priority": "low",
"notification_from": "sampleapp",
"email_to": "nameb@ccsmed.com;nameb@ccsmed.com",
"email_from": "namec@ccsmed.com"
}
"""
system = EmailNotificationSystem.model_validate_json(json_data)
print(system)