Введение FastAPI

08 Янв 2021 , 373

Если вы разрабатываете свои проекты на Django , то вы легко можете разработать API с помощью замечательной библиотеки Django REST framework(DRF). Но иногда бывает полезно рассматривать альтернативы и другие технологии , которые специально заточены для реализации данных задач. И при том эти фреймворки учитывают плюсы и минусы существующих технологий и разрабатываются с учетом новых возможностей языка Python.  Одним из таких современных фреймворков , который разрабатывался для построения API является фреймворк FastAPI.

Многие в сети советуют для написания API использовать фреймворк Flask , но использовать для построения API еще один синхронный фреймворк для меня является нецелесообразным , учитывая , что есть такой прекрасный асинхронный фреймворк FastAPII , который базируется на другом замечательном Python фреймворке Starlette. Если вы еще не писали асинхронный код и не использовали новые возможности питона , такие как подсказки типов(type hinting) , то при использовании данного фреймворка то вы успешно этого будете делать.

Из требований вы должны использовать Python 3.6 и выше.

Мы создадим API для наших постов. Реализуем все методы CRUD (Create, Read, Update,Delete)

Вначале установим FastAPI


pip install fastapi

В качестве зависимостей данный фреймворк тянет за собой фреймворк Starlette и библиотеку Pydantic, которая используется для парсинга и валидации данных

Для запуска приложений на FastAPI нам нужен ASGI сервер. Поэтому мы установим Uvicorn


pip install uvicorn[standard]

Для хранения наших постов мы будем использовать базу данных SQLite. В Django для работы с базой данных у нас есть встроенный Django ORM. Обычно для работы с БД на других фреймворках Python я использую замечательную библиотеку SQLAlchemy , которая в своем составе имеет SQLAlchemy ORM. Но так на FastAPI мы с БД ходить взаимодействовать в асинхронном редиме , то мы не можем использовать SQLAlchemy ORM. Но мы то знаем , что SQLAlchemy содержит не только SQLALchemy ORM , но и SQLAlchemy Core , который поддерживает асинхронный стиль.

Поэтому мы установим encode/databases для SQLite следующим образом


pip install databases[sqlite]

Тут мы используем SQLite для нашего примера (так как его легко использовать), а так на продакшене я бы рекомендовал использовать PostgreSQL. Для PostgreSQL мы encode/databases должны установить следующим образом


pip install databases[postgresql]

Давайте создадим код с помощью SQLAlchemy для таблицы posts. Для этого мы должны испортировать библиотеку sqlalchemy , создать metadata объект и с помощью sqlalchemy.Table укажем , какие столбы будет иметь наша таблица posts. Как видно из нижеследующего кода , когда мы обявляем поля для таблицы posts с помощью sqlalchemy.Table , то в качестве параметра мы передаем объект metadata


import sqlalchemy
metadata = sqlalchemy.MetaData()

posts = sqlalchemy.Table(
    "posts",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.INTEGER, primary_key=True),
    sqlalchemy.Column("title", sqlalchemy.String),
    sqlalchemy.Column("text", sqlalchemy.String),
    sqlalchemy.Column("is_published", sqlalchemy.Boolean),
)

Далее подключимся к SQLite


import databases
DATABASE_URL = "sqlite:///./blogapi.db"
database = databases.Database(DATABASE_URL)
engine = sqlalchemy.create_engine(
    DATABASE_URL, connect_args={"check_same_thread": False}
)

metadata.create_all(engine)

Создадим Pydantic модели. Это позволит нам валидировать входные данные и если входящие данные не будут соответствовать типам , то возникнут исключения валидации. Таже входящие данные будут сериализированы и документированы и этом мы можем увидеть в документации OpenAPI , которая генерируется автоматически и которую мы можем посмотреть в двух форматах: Swagger и Redoc


from pydantic import BaseModel


class PostIn(BaseModel):
    title: str
    text: str
    is_published: bool


class Post(BaseModel):
    id: int
    title: str
    text: str
    is_published: bool

Ниже я покажу как использовать эти модели.

Сейчас нам необходимо создать приложение на FastAPI , а также создадим обработчики событий для подключения к базе данных и для разъединения.


app = FastAPI()


@app.on_event("startup")
async def startup():
    await database.connect()


@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()

Тут мы подробно остановимся

Тут приведен полный листинг кода


from typing import List
import databases
import sqlalchemy
from fastapi import FastAPI
from pydantic import BaseModel


DATABASE_URL = "sqlite:///./blogapi.db"

database = databases.Database(DATABASE_URL)

metadata = sqlalchemy.MetaData()

posts = sqlalchemy.Table(
    "posts",
    metadata,
    sqlalchemy.Column("id", sqlalchemy.INTEGER, primary_key=True),
    sqlalchemy.Column("title", sqlalchemy.String),
    sqlalchemy.Column("text", sqlalchemy.String),
    sqlalchemy.Column("is_published", sqlalchemy.Boolean),
)

engine = sqlalchemy.create_engine(
    DATABASE_URL, connect_args={"check_same_thread": False}
)

metadata.create_all(engine)

class PostIn(BaseModel):
    title: str
    text: str
    is_published: bool


class Post(BaseModel):
    id: int
    title: str
    text: str
    is_published: bool

app = FastAPI()


@app.on_event("startup")
async def startup():
    await database.connect()


@app.on_event("shutdown")
async def shutdown():
    await database.disconnect()


@app.get('/posts/', response_model=List[Post])
async def read_posts():
    query = posts.select()
    return await database.fetch_all(query)


@app.post("/posts/", response_model=Post)
async def create_post(post: PostIn):
    query = posts.insert().values(title=post.title, text=post.text, is_published=post.is_published)
    last_record_id = await database.execute(query)
    return {**post.dict(), "id": last_record_id}


@app.delete("/posts/{post_id}")
async def delete_post(post_id: int):
    query = posts.delete().where(id == post_id)
    await database.execute(query)
    return {"detail": "Post deleted", "status_code": 204}

Большой плюс FastAPI в том , что он автоматически генерит документацию в формате OpenAPI, который вы можете смотреть в формате Swagger , если перейдете по адресу: http://127.0.0.1:8000/docs

Таже вы можете посмотреть сгенерированную документацию OpenAPI в формате Redoc , если вы перейдете по адресу: http://127.0.0.1:8000/redoc

Заключение

В данной статье мы написали простой API для постов ,с помощью фреймворка FastAPI

comments powered by Disqus

Подписка

Подпишитесь на наш список рассылки, чтобы получать обновления из блога

Рубрики

Теги