Розробка Python (Django/FastAPI) бекенду для мобільних додатків
Python — другий за популярністю язык для мобільних бекендів після Node.js. Дві домінуючі опції: Django REST Framework — batteries-included, ORM, admin, auth з коробки; FastAPI — асинхронний, типобезпечний, швидкий старт. Вибір між ними залежить від швидкості розробки, продуктивності та розміру команди.
FastAPI: коли потрібна швидкість та типізація
FastAPI будується на Pydantic та Starlette. Кожен endpoint автоматично валідує вхідні дані через типові анотації та генерує OpenAPI-документацію:
from fastapi import FastAPI, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer
from pydantic import BaseModel, UUID4
from sqlalchemy.ext.asyncio import AsyncSession
app = FastAPI()
oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/auth/token")
class CreatePostRequest(BaseModel):
title: str
content: str
author_id: UUID4
class PostResponse(BaseModel):
id: UUID4
title: str
content: str
created_at: datetime
class Config:
from_attributes = True
@app.post("/posts", response_model=PostResponse, status_code=201)
async def create_post(
body: CreatePostRequest,
db: AsyncSession = Depends(get_db),
current_user: User = Depends(get_current_user),
):
if body.author_id != current_user.id:
raise HTTPException(status_code=403, detail="Forbidden")
post = await post_service.create(db, body)
return post
Pydantic v2 (Rust-based) валідує дані швидше, ніж більшість альтернатив. response_model автоматично серіалізує ORM-об'єкт та приховує поля, яких немає у схемі (password-хеш не попаде у відповідь).
SQLAlchemy 2.x + AsyncSession для асинхронної роботи з PostgreSQL через asyncpg:
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker
engine = create_async_engine(settings.DATABASE_URL) # postgresql+asyncpg://...
AsyncSessionLocal = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
async def get_db():
async with AsyncSessionLocal() as session:
yield session
Alembic для міграцій схеми БД — генерує diff між моделями та поточною БД.
JWT Автентифікація
from jose import JWTError, jwt
from datetime import datetime, timedelta
def create_access_token(user_id: str) -> str:
expires = datetime.utcnow() + timedelta(minutes=15)
return jwt.encode(
{"sub": user_id, "exp": expires, "type": "access"},
settings.JWT_SECRET,
algorithm="HS256",
)
async def get_current_user(
token: str = Depends(oauth2_scheme),
db: AsyncSession = Depends(get_db),
) -> User:
try:
payload = jwt.decode(token, settings.JWT_SECRET, algorithms=["HS256"])
user_id: str = payload.get("sub")
except JWTError:
raise HTTPException(status_code=401, detail="Could not validate token")
user = await user_repo.get(db, user_id)
if not user:
raise HTTPException(status_code=401, detail="User not found")
return user
Django REST Framework: коли потрібен повний стек
DRF побеждає, коли потрібно швидко отримати admin-панель, потужний ORM з select_related/prefetch_related, вбудовані permissions та throttling:
# serializers.py
class PostSerializer(serializers.ModelSerializer):
author_name = serializers.SerializerMethodField()
class Meta:
model = Post
fields = ['id', 'title', 'content', 'author_name', 'created_at']
read_only_fields = ['id', 'created_at']
def get_author_name(self, obj):
return obj.author.get_full_name()
# views.py
class PostViewSet(ModelViewSet):
serializer_class = PostSerializer
permission_classes = [IsAuthenticated]
throttle_classes = [UserRateThrottle]
def get_queryset(self):
return Post.objects.filter(author=self.request.user)\
.select_related('author')\
.order_by('-created_at')
select_related вирішує N+1 проблему: один SQL JOIN замість запиту для кожного автора. prefetch_related — для many-to-many.
django-channels для WebSocket (чат, realtime). Celery + Redis для фонових задач (відправка email, push-сповіщень, важкі обчислення).
# tasks.py
from celery import shared_task
import firebase_admin.messaging as fcm
@shared_task(bind=True, max_retries=3, default_retry_delay=60)
def send_push_notification(self, token: str, title: str, body: str):
try:
message = fcm.Message(
token=token,
notification=fcm.Notification(title=title, body=body),
android=fcm.AndroidConfig(priority='high'),
apns=fcm.APNSConfig(payload=fcm.APNSPayload(aps=fcm.Aps(sound='default'))),
)
fcm.send(message)
except Exception as exc:
raise self.retry(exc=exc)
Порівняння підходів
| Критерій | FastAPI | Django REST Framework |
|---|---|---|
| Async з коробки | Так (asyncio) | Частково (Django 4.1+) |
| Швидкість старту | Висока | Середня |
| Admin-панель | Ні (сторонні) | Вбудована |
| ORM | SQLAlchemy / Tortoise | Django ORM |
| Документація API | Автогенерація (Swagger) | drf-spectacular |
| Підходить для | Нові проекти, API-only | Швидкий MVP з admin |
Типова проблема: синхронний код у async FastAPI
# Погано: блокує event loop
@app.get("/data")
async def get_data():
return requests.get("https://external-api.com/data").json() # sync!
# Добре
@app.get("/data")
async def get_data():
async with httpx.AsyncClient() as client:
response = await client.get("https://external-api.com/data")
return response.json()
requests у async def блокує весь event loop: всі паралельні запити стають в чергу. httpx.AsyncClient — асинхронна альтернатива.
Розгортання
FastAPI/Django запускається через Uvicorn + Gunicorn (кілька воркерів × async). Docker з багатоступеневою збіркою для мінімального образу. Nginx як reverse proxy. PostgreSQL + Redis у docker-compose для локаля, RDS + ElastiCache для AWS.
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --user -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /root/.local /root/.local
COPY . .
CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000"]
Що входить у розробку
Проектування API під вимоги мобільного клієнта. Налаштування PostgreSQL + Alembic міграції. Auth (JWT). CRUD-модулі. Push-сповіщення (Firebase Admin SDK). Фонові задачі (Celery). Docker + CI/CD. Документація OpenAPI.
Терміни
MVP (Auth + 3–5 ресурсів): 2–3 тижні. Повноцінний бекенд: 1–3 місяці. Вартість — після аналізу вимог.







