FastAPI — как датаклассы на максималках упрощают веб-разработку?
В эпоху реактивных фреймворков, таких как React, Vue.js, Angular и SVELTE, бекенд разработка смещается в сторону API — нам достаточно сделать CRUD-ы, настроить валидацию данных и (опционально) сделать авторизацию пользователя. В таком случае фронтенд-разработка максимально отделена от бекенд-части, тот же рендеринг шаблонов ложится на браузер пользователя.
Для создания RESTful ресурсов есть дополнения для популярных библиотек. Например, для Flask можно воспользоваться Flask-RESTful, или более близкой к сегодняшней теме библиотекой Flask-REST-JSONAPI (эта реализация устарела и не поддерживается, есть доработанный форк с расширяющим возможности дополнением).
Для Django есть Django REST framework. Все эти и другие подобные решения отлично подходят для изменения курса разработки существующего проекта. Но что, если прямо сейчас необходимо начать проект с нуля, вы точно знаете, что нужно будет разрабатывать только API, а ещё хочется чего-то нового? Вот тут на сцене появляется FastAPI! Чем же примечателен этот фреймворк?
Ключевые преимущества можно прочитать на главной странице сайта, но главное, что нас сегодня интересует, это то, как здесь реализована работа с аннотациями типов. Если вы знакомы с датаклассами или библиотекой attrs, то уже понимаете суть pydantic — библиотеки, на которой и основан FastAPI. Давайте же посмотрим, как это работает (пропустим официальный Hello World, он ничем не отличается от того же Flask).
Параметры в url
Похожим на Flask/Django образом указываем в пути переменную. Но делаем это в фигурных скобках, а тип объявляем в функции, которая будет обрабатывать запрос.
from fastapi import FastAPI app = FastAPI() @app.get("/user/{user_id}/") def get_user(user_id: int): return {"user_id": user_id}
Также необходимо установить
Автоматически сгенерированная документация Swagger:
Если хотите запускать не из терминала, а напрямую в коде, то достаточно импортировать
uvicorn и добавить в конце файла строчкуuvicorn.run(app) .
Здесь мы можем в удобном виде тестировать созданные ресурсы. Но что же насчёт валидации? При попытке перейти на http://127.0.0.1:8000/user/spam/ мы получим такую ошибку:
{ "detail": [ { "loc": [ "path", "user_id" ], "msg": "value is not a valid integer", "type": "type_error.integer" } ] }
Библиотека выполнила валидацию за нас, поэтому мы можем быть уверены, что в функцию нам придёт именно
Валидация объектов
Теперь взглянем на более сложные запросы. Например,
class UserBase(BaseModel): """ Базовая модель пользователя. Задавать полное имя не обязательно """ nickname: str full_name: str = None class UserIn(UserBase): """ Описываем, какие данные ожидаем получить на вход при создании пользователя. Тут будут унаследованы все поля """ class UserOut(UserBase): """ То, как будет выглядеть возвращаемый объект. Добавляем поле `id`, оно будет "присвоено" при "сохранении" """ id: int
Теперь объявляем роут. Там проставляем айди-объекта в результат (необходимое поле для возврата на фронт):
@app.post("/user/", response_model=UserOut) def create_user(user_in: UserIn): user_out = UserOut(**user_in.dict(), id=42) return user_out
Можем перейти на страницу документации и посмотреть спецификацию. Тут мы видим и какие данные нужно прислать на сервер, и какие будут возвращены клиенту:
Спецификация POST-запроса:
При запросе данные будут провалидированы, поэтому в переменной
Теперь выполняем
{ "nickname": "OTUS" }
В ответ нам приходит такой JSON:
{ "nickname": "OTUS", "full_name": null, "id": 42 }
Здесь мы видим, что всё пришло, как мы и ожидали. FastAPI выполнит валидацию полей "под капотом", а нам нужно заниматься только логикой приложения.
И это только самая верхушка возможностей валидации. Если вы были заинтересованы, то загляните в User Guide и Advanced User Guide — будете приятно удивлены количеством всего, что поможет упростить разработку! А вот, например, готовый шаблон full-stack проекта.
Кстати, ещё один пункт, как библиотека ускоряет разработку помимо того, что занимается валидацией данных за вас: благодаря pydantic и аннотациям типов ваша среда разработки будет подсказывать все свойства и методы объектов, с которыми вы работаете, а также подсвечивать ошибки, которые так легко допустить, изменив возвращаемые из функции данные, или просто опечатавшись.