В контексте Pydantic и FastAPI обязательные поля — это те, которые должны быть предоставлены пользователем в запросе. Если такие поля отсутствуют, FastAPI тут же выдаст ошибку с подробным описанием, чего именно не хватает.
Опциональные поля, напротив, могут быть либо представлены, либо отсутствовать. Если их нет в запросе, система не выйдет из себя, а просто использует значение по умолчанию или оставит это поле пустым.
Где это применяется?
- Обязательные поля: например, в приложении для регистрации пользователя обычно важно, чтобы поля
usernameиpasswordприсутствовали. Без них никак. - Опциональные поля: если в форме регистрации есть поле
middle_name(отчество), то вполне разумно, что не все захотят его указывать.
Использование Pydantic для работы с обязательными полями
Давайте начнём с самого базового примера простейшей модели с обязательными полями.
from pydantic import BaseModel
class User(BaseModel):
username: str
email: str
age: int
В этой модели поля username, email и age являются обязательными. Если хотя бы одно из них отсутствует в данных, отправленных в наш API, FastAPI вернёт следующую ошибку:
{
"detail": [
{
"loc": ["body", "username"],
"msg": "field required",
"type": "value_error.missing"
}
]
}
Как работает валидация обязательных полей
Pydantic автоматически валидирует, что все указанные поля присутствуют и соответствуют своим типам. Например:
- Поле
usernameдолжно быть строкой (типstr). - Поле
ageдолжно быть целым числом (типint).
Работа с опциональными полями
Чтобы создать опциональное поле, оно должно либо:
- Иметь значение по умолчанию.
- Задать тип в виде объединения типов, например
str | None.
Вот пример:
from pydantic import BaseModel
class User(BaseModel):
username: str
email: str
middle_name: str | None = None # Поле может отсутствовать
Здесь поле middle_name опционально, так как мы указали тип str | None и предоставили значение по умолчанию (None).
Пример использования опциональных полей
Вот как это будет работать на практике:
- Если пользователь отправляет JSON:
То FastAPI обработает запрос без проблем, даже если{ "username": "john_doe", "email": "john@example.com" }middle_nameне указано. - Если пользователь всё же укажет
middle_name:
Тогда{ "username": "john_doe", "email": "john@example.com", "middle_name": "Edward" }middle_nameбудет содержать значение"Edward".
Сравнение обязательных и опциональных полей
| Поле | Пример кода | Когда необходимо? |
|---|---|---|
| Обязательное поле | username: str |
Данные критически важны для работы модели |
| Опциональное поле | middle_name: str | None = None |
Данные могут отсутствовать в запросе |
| С дефолтным значением | is_active: bool = True |
Используется значение по умолчанию, если поле пустое |
Углубляемся: работа с Required и значениями по умолчанию
Если вы хотите, чтобы поле было опциональным и имело значение по умолчанию, достаточно просто задать это значение в модели:
class User(BaseModel):
is_active: bool = True # Значение по умолчанию — True
Теперь даже если пользователь не предоставит is_active, оно всё равно будет автоматически установлено в значение True.
Если вы хотите быть максимально строгими, то можете указать, что поле не может быть пустым, используя ... (три точки):
from pydantic import Required
class Product(BaseModel):
name: str = Field(..., description="Название продукта")
price: float
Теперь name стал абсолютно обязательным: FastAPI никогда не пропустит его отсутствие.
Примеры из реальной жизни
Пример 1: регистрация пользователя
Добавим обязательные и опциональные поля в эндпоинт регистрации нового пользователя.
from fastapi import FastAPI
from pydantic import BaseModel, EmailStr
app = FastAPI()
class User(BaseModel):
username: str
email: EmailStr
middle_name: str | None = None
age: int
is_active: bool = True # Дефолтное значение
@app.post("/register")
async def register_user(user: User):
return {"message": f"User {user.username} registered successfully!"}
Тестируем этот эндпоинт:
- Если отправим:
Ответ будет:{ "username": "john_doe", "email": "john@example.com", "age": 25 }{ "message": "User john_doe registered successfully!" } - Если уберём
username:
API вернёт ошибку:{ "email": "john@example.com", "age": 25 }{ "detail": [ { "loc": ["body", "username"], "msg": "field required", "type": "value_error.missing" } ] }
Пример 2: фильтрация товаров
Добавим опциональный параметр для фильтрации списка товаров.
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class ProductFilter(BaseModel):
category: str | None = None
min_price: float | None = None
max_price: float | None = None
@app.get("/products")
async def filter_products(filter: ProductFilter):
return {"filter": filter.dict()}
Такой эндпоинт позволяет фильтровать товары с помощью опциональных параметров. Пользователь может предоставить часть данных, например, только категорию или минимальную цену.
Типичные ошибки и особенности работы
Частая ошибка — забыть указать значение по умолчанию для опционального поля. Например:
class User(BaseModel):
middle_name: str | None # Ошибка! Нет значения по умолчанию!
Такое поле станет обязательным, несмотря на использование Optional. Поэтому всегда добавляйте = None, если поле должно быть опциональным.
Ещё одна ошибка — попытка совместить Required и дефолтное значение. Если поле имеет значение по умолчанию, оно уже не считается строго обязательным.
Вот и всё на сегодня, друзья! Теперь ваши формы, запросы и модели будут структурированы, как банковский отчёт, и никто не сможет пропустить заполнение важных данных. А вы — на шаг ближе к статусу мастера FastAPI!
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ