Валидация данных является ключевым аспектом разработки веб-приложений. Когда ваш API принимает данные от пользователей, важно убедиться, что эти данные корректны и соответствуют ожидаемым форматам. FastAPI использует Pydantic для автоматической валидации данных, что позволяет разработчикам писать меньше кода и концентрироваться на логике приложения.
Основные концепции Pydantic
Pydantic — это библиотека для проверки типов данных и валидации данных в Python. Она позволяет создавать модели данных, которые автоматически проверяют, соответствуют ли переданные данные заданным типам и условиям. Pydantic широко используется в FastAPI для валидации входных данных запросов и ответов.
Ключевые возможности Pydantic:
- Автоматическая проверка типов: Pydantic автоматически проверяет типы данных и конвертирует их в указанные типы.
- Обработка значений по умолчанию: Можно задать значения по умолчанию для полей модели.
- Обработка ошибок: Pydantic генерирует детализированные сообщения об ошибках, если данные не соответствуют заданным условиям.
- Декларативный стиль: Модели данных создаются декларативно с использованием аннотаций типов Python.
Создание моделей данных с Pydantic
Создадим несколько моделей данных, чтобы продемонстрировать возможности Pydantic. Мы создадим простую CRM-систему с моделями для клиентов и заказов.
Пример 1: Модель данных для клиента
from pydantic import BaseModel, EmailStr
from typing import Optional
class Customer(BaseModel):
id: int
name: str
email: EmailStr
address: Optional[str] = None
В этой модели Customer содержит следующие поля:
- id: целое число (обязательное поле)
- name: строка (обязательное поле)
- email: строка, соответствующая формату email (обязательное поле)
- address: строка (необязательное поле)
Пример 2: Модель данных для заказа
from pydantic import BaseModel
from typing import List
class OrderItem(BaseModel):
item_id: int
quantity: int
class Order(BaseModel):
order_id: int
customer_id: int
items: List[OrderItem]
total_price: float
В этой модели Order содержит следующие поля:
- order_id: целое число (обязательное поле)
- customer_id: целое число (обязательное поле)
- items: список объектов OrderItem (обязательное поле)
- total_price: число с плавающей точкой (обязательное поле)
Использование моделей данных в FastAPI
Теперь, когда у нас есть модели данных, мы можем использовать их для валидации входных данных в FastAPI. Создадим эндпоинты для создания клиентов и заказов.
Пример 3: Эндпоинт для создания клиента
from fastapi import FastAPI
app = FastAPI()
@app.post("/customers/")
async def create_customer(customer: Customer):
return customer
В этом примере мы определили эндпоинт /customers/, который принимает POST-запрос. Входные данные должны соответствовать модели Customer. FastAPI автоматически валидирует данные и передаст их в функцию create_customer, если они соответствуют модели.
Пример 4: Эндпоинт для создания заказа
@app.post("/orders/")
async def create_order(order: Order):
return order
Здесь мы определили эндпоинт /orders/, который принимает POST-запрос с данными, соответствующими модели Order.
Обработка ошибок валидации
Когда данные не соответствуют модели, Pydantic генерирует детализированные сообщения об ошибках. FastAPI автоматически обрабатывает эти ошибки и возвращает понятные ответы клиенту.
Пример 5: Пример ошибки валидации
Отправьте POST-запрос на /orders/ с некорректными данными:
{
"order_id": 1,
"customer_id": 123,
"items": [
{
"item_id": 1,
"quantity": "three"
}
],
"total_price": 100.0
}
Ответ будет содержать информацию об ошибке:
{
"detail": [
{
"loc": ["body", "items", 0, "quantity"],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
Дополнительные возможности
Pydantic предоставляет не только базовую проверку типов данных, но и ряд дополнительных функций, которые значительно упрощают разработку веб-приложений. В дополнение к уже рассмотренным концепциям, рассмотрим следующие возможности:
Валидация значений
Помимо проверки типов данных, Pydantic позволяет задавать дополнительные условия для проверки значений. Это может включать проверку диапазона числовых значений, минимальной или максимальной длины строк и других параметров. Рассмотрим пример:
from pydantic import BaseModel, constr, condecimal
class Product(BaseModel):
name: constr(min_length=3, max_length=50)
price: condecimal(gt=0)
Здесь constr используется для проверки строки по длине, а condecimal для проверки положительного числа с плавающей точкой.
Обработка значений по умолчанию
Часто требуется задать значения по умолчанию для полей модели. Pydantic поддерживает это с помощью аргументов по умолчанию в объявлении полей:
from pydantic import BaseModel
class User(BaseModel):
id: int
name: str = 'John Doe'
age: int = 25
Здесь name и age имеют значения по умолчанию, которые будут присвоены, если они не будут переданы при создании экземпляра модели.
Аннотации для вложенных моделей и контейнеров
Pydantic позволяет объявлять аннотации для вложенных моделей и контейнеров (например, списков или словарей), что обеспечивает рекурсивную валидацию данных:
from pydantic import BaseModel
from typing import List
class Item(BaseModel):
name: str
price: float
class Cart(BaseModel):
owner_id: int
items: List[Item]
Здесь Cart содержит список items, каждый из которых должен быть экземпляром Item.
Кастомные валидаторы
Для более сложных проверок данных можно использовать кастомные валидаторы, которые являются методами модели и вызываются при валидации. Пример кастомного валидатора:
from pydantic import BaseModel, validator
class User(BaseModel):
username: str
password: str
@validator('password')
def validate_password(cls, v):
assert len(v) >= 6, 'password must be at least 6 characters'
return v
Этот валидатор проверяет, что пароль состоит как минимум из 6 символов.