I have those 3 fields: event, category, subcategory Depending on the name I allow different categories and depending on the category I allow different subcategories. Example:
How can I do that? I need it for FastAPI validation and if there is a way of doing it more efficiently that would be great.
I couldn't find an easy way to implement this dependence with the Pydantic schema itself.
I used model_validator
(A newer version of validator
suggested in the comments) with a dictionary schema.
Example
Schema defining the the allowed name, category and subcategory combinations:
events_schema = {
"""
Example:
"name": {
"category": ["subcategory", "subcategory"],
"category": ["subcategory", None], # None If we want to allow a category without a subcategory.
None: [None] # If we want to allow events without a category and subcategory.
},
"""
"a": {
"aa": ["aaa", "aab"],
"ab": ["aba", "abb"],
None: [None]
},
"b": {
"ba": ["bba", "bbb"],
"bb": ["bca", "bcb"],
"bc": [None]
},
# More events can be added here
}
Use Pydantic's model_validator to validate the request data:
class EventRequest(BaseModel):
name: str
category: Optional[str]
subcategory: Optional[str]
@model_validator(mode="after")
def verify_event_hierarchy(self) -> "EventRequest":
# Check if name exists in the hierarchy
if self.name not in events_schema:
raise ValueError(f"Invalid name: '{self.name}'")
# Check if category exists for the given name
if self.category not in events_schema[self.name]:
raise ValueError(f"Invalid category '{self.category}' for name '{self.name}'.")
# Check if subcategory exists for the given category under the name
if self.subcategory not in events_schema[self.name].get(self.category, []):
raise ValueError(
f"Invalid subcategory '{self.subcategory}' for category '{self.category}' under name '{self.name}'."
)
return self