In the previous article, we reviewed some of the common scenarios of Pydantic that we need in FastAPI applications. In this one, we will have a look into, How to validate the request data. As discussed earlier, We can not trust user-given data, so we need to preprocess them.
Let's take a very simple example, say we don't want the title to be less than 5 characters in length. This can be done as follow:
from pydantic import BaseModel, Field
class Blog(BaseModel):
title: str = Field(...,min_length=5)
is_active: bool
Blog(title="hi",is_active=False)
# Output: ValidationError: 1 validation error for Blog title
# ensure this value has at least 5 characters
min_length is just one of the available hooks, To know of more of the hooks see hooks for str, hooks for int, hooks for list. There are many more hooks e.g.
gt: int = None
: enforces integer to be greater than the set valuemultiple_of: int = None
: enforces integer to be a multiple of the set valuestrip_whitespace: bool = False
: removes leading and trailing whitespaceregex: str = None
: regex to validate the string againstValidation with Custom Hooks
In real-world projects and products, these validations are rarely sufficient. Say, we want to validate the title. If the title contains 'delete from' substring, We want to raise a ValueError. We can achieve this as follow:
from pydantic import BaseModel,Field, validator
class Blog(BaseModel):
title: str = Field(...,min_length=5)
is_active: bool
@validator("title")
def validate_no_sql_injection(cls, value):
if "delete from" in value:
raise ValueError("Our terms strictly prohobit SQLInjection Attacks")
return value
Blog(title="delete from",is_active=True)
# Output: ValidationError: 1 validation error for Blog title
# Our terms strictly prohobit SQLInjection Attacks
In the above class Blog, We made a static class method, this takes in the value to validate. We do our checks and raise an Error if we find some issue. If everything looks well, we have to return a value that will be assigned to that property. We can even alter the value if required.
Validating interdependent properties with custom hooks
Many times, one property is dependent on another property of the class. I would like to quote a very beautiful example from pydantic docs. Say, we require the users to send their email, password, and confirm_password for registration. It is evident that we need to check if the password has the same value as that of confirm_password. In such cases, single field validation will not suffice. Pydantic provides a root_validator decorator which helps to tackle such cases.
from pydantic import BaseModel, root_validator
class CreateUser(BaseModel):
email : str
password :str
confirm_password :str
@root_validator()
def verify_password_match(cls,values):
password = values.get("password")
confirm_password = values.get("confirm_password")
if password != confirm_password:
raise ValueError("The two passwords did not match.")
return values
CreateUser(email="[email protected]",password="1234",confirm_password="123")
# Output: ValidationError: 1 validation error for CreateUser __root__
# The two passwords did not match. (type=value_error)
There are many more features, however, these are the most common and useful patterns for FastAPI. We will look into some more features in the course itself.
Brige the gap between Tutorial hell and Industry. We want to bring in the culture of Clean Code, Test Driven Development.
We know, we might make it hard for you but definitely worth the efforts.
© Copyright 2022-23 Team FastAPITutorial