logo
Ещё

FastAPI с нуля на Python

FastAPI – это самый популярный и самый простой фреймворк для создания API на Python. Все, что вам нужно сделать для разработки своего первого API – установить зависимости, подключить фреймворк и потратить 10 минут на создание эндпоинтов. О документации можете не беспокоиться – FastAPI все сделает за вас, причем – в двух экземплярах (по двум разным стандартам). Ниже мы покажем, как все это работает.

Что такое FastAPI?

FastAPI – это фреймворк для быстрого создания API веб-приложений. По опросам 2023 года этот фреймворк был 3-м по популярности среди всех фреймворков Python и самым любимым. Основная фишка фреймворка – в том, что все технические детали реализации он прячет «под капот», и разработчику остается только реализовать непосредственно обработку конкретных запросов – для этого пишутся эндпоинты, то есть адреса, по которым клиент должен обратиться, чтобы получить ответ от API. FastAPI создан поверх двух других библиотек – Starlette и Pydantic: первая предоставляет инструменты для клиент-серверного взаимодействия, вторая работает со схемами данных; FastAPI объединяет их, прячет детали и добавляет высокоуровневые методы работы с API, поэтому вам с «подлежащими» библиотеками работать почти не придется.

Как написать приложение на FastAPI с нуля?

Зависимости и другая подготовка

Для того, чтобы создать приложение, вам нужно иметь под рукой любой редактор со встроенной командной строкой – VSCode или PyCharm вполне подойдут. Кроме того – вам нужен сервер, на котором ваше приложение будет запускаться. К счастью, все это можно установить одной командой:

pip install fastapi uvicorn

Естественно, у вас должен быть установлен пакетный менеджер Python – pip. Собственно, по серверной части – все, можно переходить к приложению. Создайте каталог для приложения, внутри создайте файл «main.py» - здесь вы будете писать приложение. В main.py должен быть следующий код:

from fastapi import FastAPI

app = FastAPI()

@app.get("/")

def read_root():

return {"message": "Hello, FastAPI!"}

Что здесь происходит:

  1. Импортируем
  2. Создаем «пустое» приложение на основе FastAPI – делается это одной строкой, «app = FastAPI()».
  3. Создаем основу API – эндпоинт. Эндпоинт – это адрес, по которому клиент может получить доступ к API. Например, для приложения по адресу «home.com» корневой эндпоинт – «/», то есть корень сайта. Если мы хотим, чтобы при обращении к нашему приложению по адресу «home.com/users» клиент получал количество пользователей, зашедших на сайт, нам нужно создать эндпоинт «/users». Эндпоинт декларируется строкой, в которой первым символом идет «@», затем указывается имя приложения, через точку указывается HTTP-метод, в скобках указывается локальный адрес. Со следующей строки начинается код эндпоинта – метод, который будет что-то возвращать клиенту.

Собственно, API создано – если кто-то обратится к корневому адресу приложения, то получит сообщение «Hello, FastAPI!». Запустите приложение командой

uvicorn main:app --reload

(команду нужно исполнять из каталога, в котором лежит main.py), и по адресу http://127.0.0.1:8000 вы увидите результат.

FastAPI, к слову, уже создал документацию для вашего API в двух версиях:


CRUD

Теперь сделаем наше приложение более реальным. Предположим, наше приложение – это магазинчик, продающий какие-либо товары. Для того, чтобы приложение стало функциональным, нам нужно: а) создать модель данных для товаров; б) реализовать CRUD – базовые методы HTTP для обмена данными (create, read, update, delete).

Для начала создадим модель данных:

from pydantic import BaseModel

class Item(BaseModel):

id: int

name: str

description: str = None

price: float

items = []

Для того, чтобы FastAPI мог распознавать данные, нам нужно реализовать их от родительского класса BaseModel, предоставляемого Pydantic. Наши товары (items) будут иметь минимальный набор данных – id, имя, описание, цену. В последней строке мы добавили пустой список – в нем мы будем хранить товары, которые будем добавлять через API.

Собственно, осталось только добавить эндпоинты, реализующие CRUD.

Create:

@app.post("/items/")

def create_item(item: Item):

items.append(item)

return item

Получаем объект Item, добавляем его в список товаров, возвращаем item – возврат присланного через API товара будет означать, что этот товар успешно добавлен.

Read:

@app.get("/items/")

def get_items():

return items

@app.get("/items/{item_id}")

def get_item(item_id: int):

for item in items:

if item.id == item_id:

return item

return {"error": "Item not found"}

Здесь у нас 2 метода. Первый – прочитать все, он возвращает список товаров. Второй метод – вернуть конкретный товар, ID которого пришло в запросе. Метод проходится по всему списку товаров, если нашел нужный – возвращает его, если ничего не нашел – возвращает ошибку.

Update:

@app.put("/items/{item_id}")

def update_item(item_id: int, new_item: Item):

for i, item in enumerate(items):

if item.id == item_id:

items[i] = new_item

return new_item

return {"error": "Item not found"}

Метод принимает ID товара, который нужно обновить, и Item – новые данные товара. Затем он проходится по всему списку товаров, и если находит нужный ID – обновляет и возвращает товар, если не находит ID – возвращает ошибку.

Delete:

@app.delete("/items/{item_id}")

def delete_item(item_id: int):

global items

items = [item for item in items if item.id != item_id]

return {"message": "Item deleted"}

Метод принимает ID, после чего через генератор создает новый список товаров, в котором нет товара с указанным ID. Когда все сделано – метод возвращает сообщение об успехе.

Все, CRUD реализован – можете запустить приложение командой

uvicorn main:app –reload

и убедиться в этом самостоятельно.

Весь код

from fastapi import FastAPI

from pydantic import BaseModel

class Item(BaseModel):

id: int

name: str

description: str = None

price: float

items = []

app = FastAPI()

@app.get("/")

def read_root():

return {"message": "Hello, FastAPI!"}

@app.post("/items/")

def create_item(item: Item):

items.append(item)

return item

@app.get("/items/")

def get_items():

return items

@app.get("/items/{item_id}")

def get_item(item_id: int):

for item in items:

if item.id == item_id:

return item

return {"error": "Item not found"}

@app.put("/items/{item_id}")

def update_item(item_id: int, new_item: Item):

for i, item in enumerate(items):

if item.id == item_id:

items[i] = new_item

return new_item

return {"error": "Item not found"}

@app.delete("/items/{item_id}")

def delete_item(item_id: int):

global items

items = [item for item in items if item.id != item_id]

return {"message": "Item deleted"}

Что делать дальше?

Естественно, это приложение вряд ли покроет все запросы бизнеса. Первое, чем вы можете заняться – добавить новые запросы, любые на ваш вкус. При желании вы можете расширить класс Item, добавив новые данные – можете придумать, чем именно этот магазин будет заниматься. Следующие 2 шага, на которые вы можете обратить внимание – добавление авторизации и подключение базы данных: авторизация нужна для того, чтобы только пользователи с нужными правами могли добавлять/удалять/получать данные; база данных нужна для долгосрочного хранения данных магазина – поскольку сейчас все записи о товарах хранятся в списке, они будут уничтожены сразу, как только вы остановите приложение.