Если Flask — это старая добрая Лада, то FastAPI — это Tesla: быстрая, стильная, всё на async, и ещё автогенерит Swagger. В этой статье мы:
- создадим REST API с FastAPI
- разберём роуты, параметры, валидацию, OpenAPI
- напишем тесты и async-эндпоинты
- и сделаем это без боли и с кайфом
📦 Установка
pip install fastapi uvicorn
Для запуска сервера:
uvicorn main:app --reload
🔧 Пример 1: Простой GET-роут
from fastapi import FastAPI
app = FastAPI() # Инициализируем приложение
@app.get("/") # GET-запрос на корень
async def root():
return {"message": "Привет, FastAPI!"}
⚡ Плюсы:
- async — сразу с поддержкой асинхронности
- /docs — автоматически доступен Swagger UI
- /redoc — альтернативная документация
✍️ Пример 2: Валидация параметров через Pydantic
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
is_offer: bool = False
@app.post("/items/")
async def create_item(item: Item):
return {"received": item}
📌 FastAPI использует Pydantic для проверки данных на входе. Ошибки? Возвращает JSON с объяснением.
🧮 Пример 3: Параметры запроса, путь, опциональные поля
from typing import Optional
from fastapi import Query
@app.get("/users/{user_id}")
async def read_user(user_id: int, q: Optional[str] = Query(None, max_length=50)):
return {"user_id": user_id, "q": q}
🔍 Используем:
- path-параметры — обязательные (user_id)
- query-параметры — опциональные (q)
- валидацию через Query
🔄 Пример 4: Асинхронные операции (например, с базой данных)
import asyncio
@app.get("/slow/")
async def slow_operation():
await asyncio.sleep(2) # симуляция задержки
return {"status": "Готово!"}
🚀 FastAPI обожает async/await. Под капотом — Starlette, так что производительность 🔥.
🧪 Пример 5: Тестируем API с TestClient
from fastapi.testclient import TestClient
client = TestClient(app)
def test_read_root():
response = client.get("/")
assert response.status_code == 200
assert response.json() == {"message": "Привет, FastAPI!"}
🧪 Автотесты без лишнего — идеально для CI/CD.
📚 Что даёт FastAPI из коробки:
ФичаКак использоватьSwagger UIhttp://localhost:8000/docsRedoc UIhttp://localhost:8000/redocАвтовалидациячерез pydantic.BaseModelAsyncasync def — работает нативноТестычерез TestClient
🎯 Что можно сделать с FastAPI:
- 🗓️ API для событий и расписаний
- 🛒 Мини-интернет-магазин (REST API)
- 👨🏫 Онлайн-курс с уроками и пользователями
- 📈 API для аналитики (с графиками через frontend)
- 🤖 Backend для Telegram-бота
Теперь переходим от "быстрого старта" к почти продакшн-ready API 💪
🧱 Добавление базы данных
FastAPI отлично дружит с разными ORM. Вот кратко по самым популярным:
1. SQLModel — от автора FastAPI
pip install sqlmodel
Пример:
from sqlmodel import SQLModel, Field, create_engine, Session
class User(SQLModel, table=True):
id: int = Field(default=None, primary_key=True)
name: str
email: str
engine = create_engine("sqlite:///db.sqlite3")
SQLModel.metadata.create_all(engine)
@app.post("/users/")
def create_user(user: User):
with Session(engine) as session:
session.add(user)
session.commit()
session.refresh(user)
return user
🔥 SQLModel объединяет в себе SQLAlchemy + Pydantic. Очень удобно.
🔐 Авторизация через JWT
Устанавливаем:
pip install "python-jose[cryptography]" passlib[bcrypt]
Добавим файл auth.py:
from jose import jwt
from datetime import datetime, timedelta
SECRET_KEY = "секретный_ключ"
ALGORITHM = "HS256"
def create_access_token(data: dict, expires_delta: timedelta):
to_encode = data.copy()
expire = datetime.utcnow() + expires_delta
to_encode.update({"exp": expire})
return jwt.encode(to_encode, SECRET_KEY, algorithm=ALGORITHM)
В эндпоинте:
@app.post("/token")
def login(user: UserLogin):
token = create_access_token({"sub": user.username}, timedelta(minutes=30))
return {"access_token": token, "token_type": "bearer"}
🔐 Добавим Depends, чтобы защищать роуты (подробно — когда будешь готов к бою 💥).
🌐 CORS и Rate-limiting
CORS:
pip install fastapi[all]
from fastapi.middleware.cors import CORSMiddleware
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # 👈 в проде указывай явно
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
Rate Limiting (ограничение запросов):
Можно использовать библиотеку slowapi:
pip install slowapi
Пример:
from slowapi import Limiter
from slowapi.util import get_remote_address
from fastapi import Request
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
@app.get("/ping")
@limiter.limit("5/minute") # 👈 максимум 5 раз в минуту
def ping(request: Request):
return {"message": "pong"}
🐳 Docker + Gunicorn + Uvicorn для продакшна
Создадим Dockerfile:
FROM python:3.11
WORKDIR /app
COPY . /app
RUN pip install --no-cache-dir -r requirements.txt
CMD ["gunicorn", "-k", "uvicorn.workers.UvicornWorker", "main:app", "--bind", "0.0.0.0:8000"]
requirements.txt должен содержать:
fastapi
uvicorn[standard]
gunicorn
sqlmodel
python-jose[cryptography]
Запуск:
docker build -t fastapi-app .
docker run -p 8000:8000 fastapi-app
🧠 Финалочка
Теперь у нас:
- ✅ Роуты и OpenAPI-документация
- ✅ Асинхронность и валидация
- ✅ Работа с БД (SQLModel)
- ✅ Авторизация через JWT
- ✅ CORS и лимиты
- ✅ Docker с Gunicorn для продакшна