Welcome back! So far in our course, we've learned a lot about FastAPI and its integration with Pydantic, an essential tool for creating and validating data models. We've also applied Pydantic to handle data in POST requests and applied basic field validations.
As you've surely noticed, data validation is crucial to maintaining the integrity of our data. But what if we need to enforce specific rules that go beyond basic field validation? That's where custom validation comes in handy, allowing us to enforce any rules necessary for our unique application needs.
So, what is custom validation? Quite simply, it's a set of rules that we can write ourselves that go beyond what field validation provides. For instance, imagine we want to ensure our captain has at least 5 years of experience. Using custom validation, we can do just that!
Instead of defining these rules in our endpoints, FastAPI allows us to define them right within our Pydantic
models. This makes our code cleaner and easier to manage, keeping our validation logic alongside our data models.
Before we dive into the implementation, let's quickly revisit our ongoing application setup. Here's our crew dataset and the CrewMember
Pydantic model:
Python1from fastapi import FastAPI 2from pydantic import BaseModel 3 4app = FastAPI() 5 6crew = [ 7 {"id": 1, "name": "Cosmo", "role": "Captain", "experience": 10}, 8 {"id": 2, "name": "Alice", "role": "Engineer", "experience": 8}, 9 {"id": 3, "name": "Bob", "role": "Scientist", "experience": 5} 10] 11 12class CrewMember(BaseModel): 13 name: str 14 role: str 15 experience: int
In the last lesson, we defined field constraints in our CrewMember
Pydantic model as part of data validation. But remember, sometimes we need more complex validation rules.
Let's add a custom validation to our CrewMember
model that checks if the person assigned as 'Captain' has more than 5 years of experience:
Python1from pydantic import model_validator 2 3class CrewMember(BaseModel): 4 name: str 5 role: str 6 experience: int 7 8 @model_validator(mode="after") 9 def validate_experience_for_captain(cls, values): 10 if values.role == 'Captain' and values.experience <= 5: 11 raise ValueError('Captain must have more than 5 years of experience') 12 return values
Here’s a detailed walkthrough of the code:
- Decorator:
@model_validator(mode="after")
means this method will run after the normal field validation. - Method Definition:
validate_experience_for_captain
is the custom validation method. Thecls
parameter allows access to the class, andvalues
is a dictionary of validated data. - Condition Check: The
if
statement checks if therole
is 'Captain' and theexperience
is less than or equal to 5 years. - Raise Error: If the condition is met, a
ValueError
is raised with a descriptive error message. - Return Values: If no condition is met, the method returns the validated values.
The @model_validator
ensures that your custom validation logic runs after all other field validations, helping you maintain a clean separation between field-level validations and more complex custom rules.
If we try to add a captain with 4 years of experience, the API will respond with a 422 Unprocessable Entity error. The response will look like this:
JSON1{ 2 "detail": [ 3 { 4 "type": "value_error", 5 "loc": [ 6 "body" 7 ], 8 "msg": "Value error, Captain must have more than 5 years of experience", 9 "input": { 10 "name": "Max", 11 "role": "Captain", 12 "experience": 4 13 }, 14 "ctx": { 15 "error": {} 16 } 17 } 18 ] 19}
This response indicates that the validation failed because the Captain
did not meet the required experience criteria. The error message provides details about which field was invalid and the specific issue, directly reflecting the ValueError
we raised in the custom validator.
In this lesson, we've discovered how to write custom validation logic for our data models in FastAPI, intensifying our control over data integrity. You're now equipped with the knowledge to employ custom validations in your APIs.
Great job getting here! As always, practice is key to solidifying these skills. So, immerse yourself in the exercises we've got in store, which will challenge you to create and use your own custom validators. Looking forward to seeing you in the next lessons as we continue our journey with FastAPI! Keep going, space cadet!