Вопросы по Python для веба: Django и FastAPI
Django и его ORM, DRF, FastAPI, SQLAlchemy, Celery, кеш, авторизация и безопасность: темы, на которых строится собес Python-бэкендера. После трека вы находите N+1 с одного взгляда и объясняете, как сервис живёт в проде.
Проверьте себя: тест по Django и FastAPI
20 вопросов, 10 минут, уровень junior, middle или senior
HTTP, WSGI и ASGI
Как запрос доходит до Python: WSGI и ASGI, gunicorn и uvicorn, синхронные и асинхронные воркеры.
Урок: WSGI и ASGI: как запрос доходит до Python-кода 7 мин- Async-вьюхи Django под WSGI
- Блокирующий вызов в uvicorn
- Цепочка middleware вокруг приложения
- Мини-WSGI-приложение с роутингом
- ASGI-серверы
- Что лежит в environ
- Путь HTTP-запроса до Django
- ASGI lifespan
Ещё 12 вопросов и задач
- Сервер, интерфейс и модель
- Зачем nginx перед gunicorn
- Путь запроса в продакшене
- runserver и --reload в проде
- Сигнатура WSGI-приложения
- Медленные клиенты и sync-воркеры
- WSGI против ASGI
- Сколько воркеров ставить и почему
- Пропускная способность sync-воркеров gunicorn
- Таймаут воркера gunicorn
- Что такое WSGI
- Зачем появился ASGI
Django: устройство
Проект и приложения, жизненный цикл запроса, URL, представления, middleware, настройки и сигналы.
Урок: Как устроен Django: от запроса до ответа 8 мин- Зачем ALLOWED_HOSTS
- Настройки из переменных окружения
- Свой URL-резолвер с конвертерами
- CONN_MAX_AGE и соединения с БД
- Контекст запроса в async Django
- DEBUG = True в продакшене
- FBV против CBV
- Маршрут Django с параметром
Ещё 14 вопросов и задач
- Проект и приложение Django
- Что проверяет check --deploy
- Что такое middleware в Django
- Жизненный цикл запроса в Django
- Когда вызывается __init__ у middleware
- Порядок middleware
- Что такое MTV в Django
- Порядок стандартных middleware
- Зачем name у маршрута и reverse
- Код-ревью Django-вьюхи
- Сигналы и массовые операции
- Где держать бизнес-логику в Django
- Что происходит при запросе к Django
- Состояние в экземпляре middleware
Django ORM и N+1
Ленивые QuerySet, select_related и prefetch_related, F и Q, annotate, транзакции и блокировки.
Урок: Django ORM: ленивые QuerySet, N+1, select_related и prefetch_related 8 мин- Задвоение сумм при нескольких annotate
- Посчитать SQL-запросы при ленивой загрузке
- Как prefetch_related склеивает данные
- exists() и count() вместо загрузки строк
- Атомарное увеличение счётчика
- Prefetch с вложенным select_related
- transaction.atomic
- Когда выполняется QuerySet
Ещё 13 вопросов и задач
- Объект Q
- Обработка миллиона строк
- Когда QuerySet выполняет SQL
- Методы QuerySet и их назначение
- Что такое проблема N+1
- Задача Celery и незакоммиченная транзакция
- Код-ревью: отчёт по клиентам на Django ORM
- Защита от двойного списания
- select_related против prefetch_related
- Как найти и исправить N+1 в Django
- Гонки данных в Django и как их предотвращать
- Зачем save(update_fields=...)
- values_list(flat=True)
Миграции
Миграции Django и Alembic, данные в миграциях, конфликты и изменения схемы без простоя.
Урок: Миграции в Django и Alembic: как менять схему без простоя 7 мин- Ограничения autogenerate в Alembic
- Порядок применения миграций по зависимостям
- Разбить перенос данных на пачки по id
- Конфликт миграций после слияния веток
- Создание индекса на большой таблице
- Alembic
- Схема expand и contract
- RunPython в миграциях Django
Ещё 12 вопросов и задач
- Почему apps.get_model в миграции данных
- Миграция встала в очередь за долгой транзакцией
- makemigrations и migrate
- Операции миграций Django
- Добавить NOT NULL поле в большую таблицу
- Порядок шагов переименования колонки без простоя
- Переименование колонки без простоя
- Код-ревью миграции данных Django
- Как вы работаете с миграциями в команде
- Миграции без простоя
- Зачем squashmigrations
- Где хранится, какие миграции применены
Django REST Framework
Сериализаторы, ViewSet и роутеры, права, пагинация, фильтры и троттлинг.
Урок: Django REST Framework: сериализаторы, вьюсеты, права и пагинация 8 мин- Сериализация с выбором полей
- Валидация как в сериализаторе DRF
- Когда выбрать курсорную пагинацию
- Чем опасен fields = "__all__"
- perform_create
- Слои валидации сериализатора
- Виды вьюх в DRF
- Классы пагинации DRF
Ещё 14 вопросов и задач
- N+1 во вложенном сериализаторе
- Запись во вложенный сериализатор
- has_object_permission и список объектов
- Порядок обработки запроса во вьюсете DRF
- PUT и PATCH в DRF
- Права по умолчанию в DRF
- Код-ревью DRF-вьюсета
- Медленная сериализация больших списков
- Зачем нужен сериализатор в DRF
- Как вы строите API на DRF
- Права доступа в DRF на уровне объектов
- Троттлинг DRF и несколько воркеров
- Порядок валидации сериализатора
- ViewSet и роутер
FastAPI и Pydantic
Маршруты и модели Pydantic v2, Depends, async и sync обработчики, фоновые задачи и lifespan.
Урок: FastAPI и Pydantic: маршруты, Depends, async и lifespan 8 мин- Откуда в FastAPI ответ 422
- Annotated в параметрах FastAPI
- BackgroundTasks или очередь задач
- httpx.AsyncClient на каждый запрос
- Разбор и проверка query-параметров
- Граф зависимостей с кешем на запрос
- Подмена зависимостей в тестах
- Сколько раз вызывается зависимость
Ещё 14 вопросов и задач
- Эндпоинт FastAPI с моделью и зависимостью
- Откуда FastAPI берёт параметры
- Валидаторы Pydantic v2
- На чём построен FastAPI
- lifespan вместо on_event
- Возможности FastAPI и их назначение
- API Pydantic v2
- Зачем response_model
- Код-ревью эндпоинта FastAPI
- Подводные камни async в FastAPI
- Почему FastAPI и как он работает
- Как FastAPI выполняет обычный def
- Пул потоков для sync-обработчиков
- Зависимость с yield
SQLAlchemy 2.0
Engine и Session, select-стиль 2.0, связи и стратегии загрузки, async-сессии и пул соединений.
Урок: SQLAlchemy 2.0: Session, стратегии загрузки и async 8 мин- Смоделировать identity map сессии
- Сколько запросов сделает selectinload
- Engine и Session в SQLAlchemy
- expire_on_commit
- Запрос с eager-загрузкой в async
- Identity map
- Стратегии загрузки связей
- Mapped и mapped_column
Ещё 14 вопросов и задач
- flush против commit
- joinedload коллекции и unique()
- Ленивая загрузка связей
- Аналоги Django ORM в SQLAlchemy
- Ошибка MissingGreenlet в async
- Как не пропустить N+1 в SQLAlchemy
- Исчерпание пула соединений
- Код-ревью async-сервиса на SQLAlchemy
- Запрос в стиле SQLAlchemy 2.0
- selectinload против joinedload
- Одна Session на несколько потоков
- Когда ORM, а когда сырой SQL
- Как вы управляете Session в веб-приложении
- Блокировка строки в SQLAlchemy
Аутентификация и права
Сессии и токены, JWT и refresh, OAuth2, хранение паролей, RBAC и проверка доступа к объекту.
Урок: Аутентификация и права в Python-бэкенде: сессии, JWT, пароли 8 мин- Аутентификация и авторизация
- Подписанный токен на hmac
- Проверка прав: роли и владение объектом
- Почему hmac.compare_digest
- Флаги cookie сессии
- Структура JWT
- RBAC
- Сессии против JWT
Ещё 14 вопросов и задач
- Что такое IDOR
- Подмена алгоритма JWT
- Зашифрован ли JWT
- Как отозвать JWT
- Угроза и защита
- OAuth 2.0 и OpenID Connect
- Поток обновления токенов
- Как хранить пароли
- Зачем PKCE
- Ротация refresh-токенов
- Код-ревью эндпоинта входа и проверки токена
- Как вы спроектируете аутентификацию в API
- Как не допустить ошибок контроля доступа
- Перебор пользователей через форму входа
Celery и очереди
Брокер и воркеры, ретраи и идемпотентность, acks_late, периодические задачи и альтернативы Celery.
Урок: Celery и очереди задач: ретраи, идемпотентность, гарантии доставки 8 мин- Что даёт acks_late
- Сколько экземпляров beat запускать
- Fan-out из миллиона задач
- Экспоненциальная задержка с джиттером
- Идемпотентный обработчик сообщений
- Компоненты Celery
- Семантики доставки
- Лимиты времени задач
Ещё 14 вопросов и задач
- Ретраи в Celery
- Идемпотентная задача списания
- Настройки Celery и их эффект
- Задача стартует раньше коммита
- Путь задачи Celery
- Transactional outbox
- Что передавать в задачу Celery
- Prefetch и долгие задачи
- Какие ошибки ретраить
- Код-ревью задачи Celery
- Как устроен Celery
- Надёжные фоновые задачи
- visibility_timeout у Redis-брокера
- Зачем очередь задач
Кеширование
Redis и кеш Django, стратегии и инвалидация, cache stampede, кеш на уровне HTTP.
Урок: Кеширование в Python-бэкенде: Redis, стратегии и инвалидация 7 мин- Что такое cache-aside
- Построить ключ кеша для запроса
- LRU-кеш с TTL по журналу операций
- Cache-aside в Django
- Cache-Control
- Уровни кеширования
- Стратегии записи в кеш
- ETag и условные запросы
Ещё 14 вопросов и задач
- Инвалидация кеша до коммита
- LocMemCache с несколькими воркерами
- Проблема кеша и решение
- Кеширование отсутствия значения
- Ключ кеша для персональных данных
- Политика вытеснения Redis
- Безопасное снятие блокировки в Redis
- Код-ревью кеширования профиля и рейтинга
- Согласованность кеша и базы
- Как вы кешируете данные в сервисе
- Что такое cache stampede
- Защита от stampede блокировкой
- Джиттер TTL
- Версионирование ключей кеша
Безопасность веб-приложения
SQL-инъекции, XSS, CSRF, SSRF, загрузка файлов, секреты и настройки Django для прода.
Урок: Безопасность Python-бэкенда: инъекции, XSS, CSRF, SSRF и секреты 8 мин- Безопасное имя загружаемого файла
- Безопасный редирект после входа
- CSRF и API
- Параметризованный запрос в SQLAlchemy
- Заголовки безопасности
- OWASP Top 10
- Хранение секретов
- Mass assignment
Ещё 14 вопросов и задач
- Уязвимость и защита
- Открытый редирект
- Сортировка по параметру из запроса
- Где ORM не спасает от инъекций
- Path traversal при отдаче файлов
- pickle от пользователя
- Код-ревью: поиск, редирект и импорт настроек
- Безопасность Python-бэкенда: что вы проверяете
- Как защитить загрузку по URL от SSRF
- Как защититься от SQL-инъекции
- Что такое SSRF
- Загрузка аватара в SVG
- Фильтр safe в шаблоне
- yaml.load и безопасная загрузка
Деплой и эксплуатация
Gunicorn и uvicorn за nginx, число воркеров, Docker, статика, health-check, логи и мониторинг.
Урок: Деплой Python-сервиса: gunicorn, uvicorn, Docker, health-check и логи 7 мин- Liveness и readiness по состоянию зависимостей
- Рассчитать число воркеров
- Порядок слоёв в Dockerfile
- Что мониторить у веб-сервиса
- Как запускают Python-сервис в проде
- Статика Django в проде
- Graceful shutdown
- Liveness и readiness
Ещё 13 вопросов и задач
- Настройки запуска и их назначение
- max_requests в gunicorn
- Где хранить загруженные файлы
- Пользователь в контейнере
- Воркеры убиваются по OOM
- Порядок rolling update
- gunicorn --preload
- Rolling update и миграции
- Сервис тормозит после релиза
- Как вы выкатываете Python-сервис
- Структурированные логи
- PYTHONUNBUFFERED в контейнере
- Число воркеров gunicorn