API списка задач
Соберём всё вместе и доведём API списка задач до вида, в котором его не стыдно отдать фронтенду или мобильному приложению.
Параметр из списка значений
from typing import Literal
@app.get("/todos")
def list_todos(sort: Literal["title", "priority"] = "title"):
...
Literal (или класс-перечисление Enum) разрешает только перечисленные значения: остальные получат 422. В /docs такой параметр показывается выпадающим списком.
Сортировка и сводки
Сложную сортировку задают ключом-кортежем: key=lambda t: (-t["priority"], t["title"].lower()) — сначала по убыванию приоритета, при равенстве — по названию. Для сводок помогают sum(...), // (округление вниз) и словари-счётчики. Не забывайте о пустых данных: done * 100 // total упадёт, если задач нет.
В JSON ключи словаря всегда строки, поэтому {2: 1} клиент получит как {"2": 1}.
APIRouter
В большом проекте маршруты раскладывают по файлам:
# todos.py
from fastapi import APIRouter
router = APIRouter(prefix="/todos", tags=["Задачи"])
@router.get("/") # → /todos/
def list_todos(): ...
@router.get("/{tid}") # → /todos/{tid}
def get_todo(tid: int): ...
# main.py
from fastapi import FastAPI
from todos import router
app = FastAPI()
app.include_router(router)
- адреса внутри роутера пишутся без префикса;
- подключают роутер один раз, обычно в главном файле после импорта модуля с маршрутами;
tagsгруппируют маршруты в/docs.
async def
@app.get("/weather")
async def weather():
async with httpx.AsyncClient() as client:
r = await client.get("https://api.example.com/weather")
return r.json()
Маршрут можно объявить через async def, если внутри есть await — асинхронный запрос к другому API или базе. Пока один запрос ждёт ответа, сервер обслуживает другие. Обычные def FastAPI запускает в отдельных потоках, так что медленный, но синхронный код лучше оставлять в обычных функциях.
Что дальше
Данные хранят в базе: с FastAPI часто используют SQLAlchemy или SQLModel (от автора FastAPI). Готовое приложение запускают командой uvicorn main:app --host 0.0.0.0 --port 8000 на сервере или в Docker.
Итог
Literal[...]— параметр из списка значений;- сортировка ключом-кортежем, сводки с защитой от пустых данных;
APIRouter(prefix=…)иapp.include_router(router);async def— когда внутри естьawait.