[Из песочницы] Почему Вы должны попробовать FastAPI?
Лого взято из Github репозитория FastAPI
FastAPI — относительно новый веб-фреймворк, написанный на языке программирования Python для создания REST (а если сильно постараться то и GraphQL) API, основанный на новых возможностях Python 3.6+, таких как: подсказки типов (type-hints), нативная асинхронность (asyncio). Помимо всего прочего, FastAPI плотно интегрируется с OpenAPI-schema и автоматически генерирует документацию для вашего API посредством Swagger и ReDoc
FastAPI построен на базе Starlette и Pydantic.
Starlette — ASGI микро-фреймворк для написания веб-приложений.
Pydantic — библиотека для парсинга и валидации данных основанная на Python type-hints.
Что говорят о FastAPI?
»[…] Я использую FastAPI очень часто в последние дни. […] Я однозначно планирую использовать его для всех ML сервисов моей команды в Microsoft. Некоторые из них интегрируются в Windows и некоторые продукты Office.»
Kabir Khan — Microsoft (ref)
«Если вы хотите выучить ещё один фреймворк для написания REST API, взгляните на FastAPI […] Он быстрый, прост в использовании и изучении. […]»
«Теперь мы используем FastAPI для наших API […] Я думаю он вам понравится! […]»
Ines Montani — Matthew Honnibal — Explosion AI founders — spaCy creators (ref) — (ref)
Минимальное API созданное с помощью FastAPI
Я постараюсь показать Вам как создать простое, но в то же время полезное API с документацией для разработчиков. Мы будем писать генератор случайных фраз!
Установка необходимых компонентов
pip install uvicorn fastapi pydantic
Новый модуль!
Uvicorn — это ASGI-совместимый веб-сервер, который мы будем использовать для запуска нашего приложения.
Для начала создадим основу нашего приложения.
from fastapi import FastAPI
app = FastAPI(title="Random phrase")
Это приложение уже работает и его можно запустить.
Пропишите данную команду в вашем терминале и откройте страничку в браузере по адресу http://127.0.0.1:8000/docs.
uvicorn <имя_вашего_файла>:app
Но пока в нашем приложении не обозначено ни одного эндпоинта — давайте это исправим!
База данных
Так как мы пишем генератор случайных фраз, мы очевидно должны их где-то хранить. Для этого я выбрал простой python-dict
.
Создадим файл db.py
и начнём писать код.
Импортируем необходимые модули:
import typing
import random
from pydantic import BaseModel
from pydantic import Field
После — обозначим две модели: входная фраза (та, которую нам будет отправлять пользователь) и «выходная» (та, которую мы будем отправлять пользователю).
class PhraseInput(BaseModel):
"""Phrase model"""
author: str = "Anonymous" # имя автора. Если не передано - используется стандартное значение.
text: str = Field(..., title="Text", description="Text of phrase", max_length=200) # Текст фразы. Максимальное значение - 200 символов.
class PhraseOutput(PhraseInput):
id: typing.Optional[int] = None # ID фразы в нашей базе данных.
После этого, создадим простой класс для работы с БД:
class Database:
"""
Our **fake** database.
"""
def __init__(self):
self._items: typing.Dict[int, PhraseOutput] = {} # id: model
def get_random(self) -> int:
# Получение случайной фразы
return random.choice(self._items.keys())
def get(self, id: int) -> typing.Optional[PhraseOutput]:
# Получение фразы по ID
return self._items.get(id)
def add(self, phrase: PhraseInput) -> PhraseOutput:
# Добавление фразы
id = len(self._items) + 1
phrase_out = PhraseOutput(id=id, **phrase.dict())
self._items[phrase_out.id] = phrase_out
return phrase_out
def delete(self, id: int) -> typing.Union[typing.NoReturn, None]:
# Удаление фразы
if id in self._items:
del self._items[id]
else:
raise ValueError("Phrase doesn't exist")
Теперь можно приступить к написанию самого API.
API
Создадим файл main.py
и импортируем следующие модули:
from fastapi import FastAPI
from fastapi import HTTPException
from db import PhraseInput
from db import PhraseOutput
from db import Database
Инициализируем наше приложение и базу данных:
app = FastAPI(title="Random phrase")
db = Database()
И напишем простой метод получения случайной фразы!
@app.get(
"/get",
response_description="Random phrase",
description="Get random phrase from database",
response_model=PhraseOutput,
)
async def get():
try:
phrase = db.get(db.get_random())
except IndexError:
raise HTTPException(404, "Phrase list is empty")
return phrase
Как Вы можете заметить, в декораторе я также указываю некоторые другие значения, нужные для генерации более красивой документации :) В официальной документации Вы можете посмотреть на все возможные параметры.
В этом куске кода, мы пытаемся получить случайную фразу из базы данных, а если база данных пуста — возвращаем ошибку с кодом 404.
Аналогично пишем другие методы:
@app.post(
"/add",
response_description="Added phrase with *id* parameter",
response_model=PhraseOutput,
)
async def add(phrase: PhraseInput):
phrase_out = db.add(phrase)
return phrase_out
@app.delete("/delete", response_description="Result of deleting")
async def delete(id: int):
try:
db.delete(id)
except ValueError as e:
raise HTTPException(404, str(e))
И всё! Наше маленькое, но полезное API — готово!
Теперь мы можем запустить приложение с помощью uvicorn, открыть интерактивную документацию (http://127.0.0.1/docs) и попробовать наше API!
Полезные материалы
Конечно, я не смог рассказать Вам о всех возможностях FastAPI, например таких как: умная DI система, middlewares, куки, стандартные методы аутентификация в API (jwt, oauth2, api-key) и многое другое!
Но целью этой статьи является не столько обзор всех возможностей этого фреймворка, а сколько толчок Вас изучить его самим. FastAPI имеет замечательную документацию с кучей примеров.
Код из статьи на Github
Официальная документация
Репозиторий на Github