Python для трудоустройства: Backend-разработчик

Курс помогает перейти от базового Python к навыкам, необходимым для первой работы в backend-разработке. Вы изучите работу с базами данных, создание API, тестирование, деплой и соберёте портфолио-проект, близкий к реальным задачам.

1. Углубление Python: ООП, типизация, пакеты и стиль кода

Углубление Python: ООП, типизация, пакеты и стиль кода

Ты уже знаешь базовые конструкции Python (функции, классы на уровне «что это», try/except). Дальше для трудоустройства на backend важно научиться писать код, который:

  • легко читать и сопровождать в команде
  • безопасно расширять без поломок
  • удобно тестировать
  • корректно упаковывать в проект и доставлять
  • В этой статье разберём четыре опоры: ООП, типизация, пакеты/структура проекта и стиль кода.

    ООП, которое используют в backend

    ООП в работе — это не «везде классы», а способ управлять сложностью: прятать детали, гарантировать инварианты (правила корректности) и делать расширение безопасным.

    Инкапсуляция и инварианты

    Инкапсуляция — когда объект сам отвечает за свою корректность, а внешний код не ломает его состояние напрямую.

    Пример инварианта: баланс счёта не должен становиться отрицательным.

    Ключевые моменты:

  • _balanceвнутренняя переменная (по соглашению), к ней не должны обращаться напрямую.
  • @property — безопасный доступ «как к полю», но с контролем.
  • проверки в методах защищают инварианты.
  • Полезно: Документация Python про property

    @classmethod и @staticmethod

    Это частая тема на собеседованиях и в реальном коде.

  • @staticmethod — обычная функция, просто лежит в классе «для группировки».
  • @classmethod — метод, который получает сам класс (cls) и часто используется как альтернативный конструктор.
  • Композиция важнее наследования

    В backend чаще выигрывает композиция: «объект имеет зависимость», а не «объект является чем-то».

  • Наследование удобно для расширения поведения, но может приводить к хрупким иерархиям.
  • Композиция проще для тестирования и подмен (например, заменять клиент к БД на фейковый).
  • !Сравнение наследования и композиции

    Абстракции: ABC и протоколы

    Когда проект растёт, появляется потребность описывать «контракт»: какие методы должен иметь объект.

    Варианты:

  • abc.ABC — классическая абстрактная база.
  • typing.Protocol — контракт для типизации (особенно удобен для duck typing: «если выглядит как утка — это утка»).
  • Полезно: Документация Python про abc

    dataclass для моделей данных

    Очень часто в backend есть сущности «данные + немного логики»: DTO, результаты запросов, параметры.

    dataclass экономит время и уменьшает количество шаблонного кода.

    frozen=True делает объект неизменяемым (полезно для предсказуемости и потокобезопасности).

    Полезно: Документация Python про dataclasses

    Типизация: как писать код, который проще поддерживать

    Type hints в Python не делают язык статическим. Это подсказки для:

  • IDE (автодополнение, навигация)
  • статических анализаторов (поиск ошибок до запуска)
  • читателя кода (контракты функций)
  • Официальный раздел: Документация Python про typing

    Базовые аннотации типов

    Важно:

  • аннотации не заставляют Python проверять типы во время выполнения
  • это делает внешний инструмент (например, mypy)
  • Optional, Union и современный синтаксис

    Когда значение может отсутствовать:

    str | None — современная запись (Python 3.10+), эквивалент Optional[str].

    Обобщённые типы (generics)

    Когда нужно «любой тип»:

    TypedDict для словарей с фиксированной схемой

    В backend много JSON-подобных структур. TypedDict помогает документировать ожидаемые ключи.

    Protocol для «утиной типизации»

    Очень полезно, когда ты хочешь принимать любой объект с нужным методом, не привязываясь к конкретному базовому классу.

    Статическая проверка: mypy

    mypy запускается отдельно и находит ошибки типа «передал не тот тип», «вернул не то», «забыл обработать None».

  • сайт проекта: mypy
  • Пример запуска:

    Модули, пакеты и структура проекта

    Backend-проект — это не один файл. Нужна структура, импорты, окружение, зависимости.

    Модуль и пакет

  • Модуль — файл something.py.
  • Пакет — папка с модулями. Исторически пакет определялся наличием __init__.py, и на практике его продолжают использовать.
  • Официально: Документация Python про модули

    Как Python ищет импорты

    Python ищет модули по sys.path (текущая папка, установленные пакеты, пути окружения). В работе важнее правило:

  • в проекте лучше делать импорты так, чтобы запуск был одинаковым в IDE, тестах и CI
  • Рекомендации:

  • используйте структуру src/ для кода приложения
  • запускайте через точку входа (например, python -m package), а не «из случайной директории»
  • Пример структуры backend-проекта

    !Пример структуры проекта

    Минимальный вариант:

    Виртуальные окружения

    Виртуальное окружение изолирует зависимости проекта.

  • официальный модуль: venv
  • Пример:

    Установка зависимостей: pip и pyproject.toml

  • pip — стандартный установщик: pip documentation
  • современный способ описывать проект — pyproject.toml: Packaging Python Projects
  • На практике часто используют менеджеры зависимостей:

  • Poetry — управление зависимостями и сборкой
  • Важная идея для работы:

  • фиксируй зависимости (версии) так, чтобы сборка была воспроизводимой
  • Стиль кода: как писать «по-командному»

    Код читают чаще, чем пишут. В командах стиль стандартизируют инструментами.

    PEP 8 и нейминг

    Базовый стандарт: PEP 8

    Критично запомнить:

  • snake_case для функций и переменных
  • PascalCase для классов
  • константы UPPER_CASE
  • длина строк и переносы лучше доверить автоформаттеру
  • Докстринги

    Докстринги нужны для публичных функций/классов и сложной логики.

    Рекомендации по соглашениям: PEP 257

    Пример:

    Инструменты качества кода

    Лучше не спорить о пробелах и переносах, а автоматизировать.

    | Задача | Инструмент | Зачем | |---|---|---| | автоформатирование | Black | единый стиль без обсуждений | | линтинг | Ruff | быстрый поиск ошибок и плохих практик | | проверка типов | mypy | ловит ошибки типов до запуска |

    Типичный минимум для backend-репозитория:

  • Black для форматирования
  • Ruff для линтинга
  • mypy для типов
  • print vs logging

    В backend вместо print почти всегда используют logging, потому что:

  • уровни логов (DEBUG, INFO, WARNING, ERROR)
  • единый формат
  • интеграция с инфраструктурой (сбор логов)
  • Документация: logging

    Пример:

    Что важно вынести из статьи

  • ООП в backend — это про инварианты, читаемость и расширяемость, а не про «всё в классы».
  • Типизация помогает ловить ошибки заранее и делает код самодокументируемым.
  • Структура проекта и окружение — обязательная часть «профессионального» Python.
  • Стиль кода закрепляется инструментами (форматтер, линтер, type checker), а не договорённостями на словах.
  • 2. HTTP и создание REST API на FastAPI: маршруты, валидация, ошибки

    HTTP и создание REST API на FastAPI: маршруты, валидация, ошибки

    В предыдущей статье ты прокачал Python как рабочий инструмент: ООП для управления сложностью, типизацию для контрактов, структуру проекта и инструменты качества. Теперь делаем следующий шаг к трудоустройству backend-разработчиком: учимся принимать HTTP-запросы, валидировать входные данные и возвращать правильные ответы и ошибки.

    FastAPI — один из самых востребованных фреймворков для Python-backend, потому что он:

  • быстрый и удобный
  • строится вокруг типизации
  • автоматически генерирует документацию OpenAPI
  • Официальная документация: FastAPI

    Что такое HTTP и зачем он нужен backend

    HTTP — это протокол, по которому клиент (браузер, мобильное приложение, другой сервис) общается с сервером.

    Запрос и ответ состоят из:

  • стартовой строки (метод/путь/версия и код статуса)
  • заголовков (headers)
  • тела (body) опционально
  • Полезные источники:

  • MDN: An overview of HTTP
  • RFC 9110 (HTTP Semantics)
  • !Схема запроса/ответа HTTP и где появляются ошибки

    Методы HTTP, которые чаще всего используются в REST

    В REST-стиле (практика построения API) обычно используют:

  • GET — получить ресурс или список
  • POST — создать ресурс
  • PUT — заменить ресурс целиком
  • PATCH — частично обновить ресурс
  • DELETE — удалить ресурс
  • Важно: метод описывает намерение, а путь — к чему применяем действие.

    Статус-коды: как сервер объясняет результат

    Статус-код — это первое, на что смотрят клиенты и другие сервисы.

    Часто используемые группы:

  • 2xx — успех (200, 201, 204)
  • 4xx — ошибка клиента (400, 401, 403, 404, 422)
  • 5xx — ошибка сервера (500 и т.д.)
  • Справочник: MDN: HTTP response status codes

    Практически важная идея:

  • 4xx означает клиент прислал плохие данные или не имеет доступа
  • 5xx означает сервер сломался или не справился
  • Быстрый старт с FastAPI

    Установка и запуск

    Обычно для разработки ставят FastAPI и сервер uvicorn.

  • документация сервера: Uvicorn
  • Минимальное приложение:

    Запуск:

    Что означает app.main:app:

  • app.main — модуль (файл main.py внутри пакета app)
  • app — переменная, в которой лежит FastAPI()
  • Автодокументация

    FastAPI генерирует OpenAPI-схему и UI:

  • GET /docs — Swagger UI
  • GET /redoc — ReDoc
  • Это важный рабочий плюс: документация всегда соответствует коду, если ты используешь типы и модели.

    Маршруты: пути, параметры и ответы

    В FastAPI обработчик называется path operation (функция, привязанная к методу и пути).

    Статический маршрут

    Path-параметры

    Path-параметр — часть URL.

    Здесь item_id: int важен сразу в трёх местах:

  • FastAPI валидирует и преобразует тип
  • в OpenAPI попадёт корректная схема
  • IDE подсказывает типы при разработке
  • Query-параметры

    Query-параметры идут после ?.

    limit и offset — типичный пример пагинации.

    Управление статус-кодом ответа

    Если ты создаёшь ресурс через POST, хорошая практика — вернуть 201 Created.

    Валидация входных данных через Pydantic-модели

    В backend большая часть ошибок и уязвимостей появляется из-за плохо проверенного ввода. FastAPI использует Pydantic-модели для валидации.

    Документация: Pydantic

    Ключевая связь с предыдущей статьёй:

  • твоя типизация теперь работает не только для mypy и IDE
  • она становится контрактом HTTP API (документация + валидация)
  • Тело запроса (JSON) как модель

    Если клиент отправит строку вместо числа или забудет поле, FastAPI вернёт ошибку валидации.

    Ошибка валидации и статус 422

    FastAPI обычно отвечает 422 Unprocessable Entity, если формат JSON корректный, но данные не проходят проверку схемы.

    Это полезно запомнить для собеседований и практики интеграций:

  • 400 Bad Request чаще про битый запрос (например, некорректный JSON)
  • 422 Unprocessable Entity чаще про запрос понятен, но данные невалидны по правилам
  • Response model: как контролировать то, что отдаёшь наружу

    Хорошая практика — отдельно описывать, что ты принимаешь и что возвращаешь.

    Плюсы:

  • наружу не «утечёт» лишнее поле
  • схема документации будет точной
  • проще рефакторить: контракт явно описан
  • Ошибки: как возвращать клиенту понятные ответы

    Есть два класса ошибок:

  • ожидаемые (например, ресурс не найден)
  • неожиданные (баг, недоступная БД)
  • FastAPI позволяет оформлять ожидаемые ошибки как часть бизнес-логики.

    HTTPException: стандартный способ вернуть ошибку

    Почему это правильно:

  • клиент получает корректный 404
  • формат ошибки предсказуем (можно обрабатывать на фронте)
  • логика читается как правило домена: «если нет — это 404»
  • Не маскируй 500 под 400

    Если сервер упал из-за бага, не выдавай это как ошибку пользователя. В реальном продакшене это ломает диагностику.

    Рабочая привычка:

  • ожидаемые ошибки оформляй как HTTPException
  • неожиданные ошибки логируй и исправляй, а клиенту возвращай 500 (обычно это делает инфраструктура и обработчики)
  • Кастомные обработчики исключений (когда нужно)

    Иногда удобно привести ошибки к единому формату (особенно в команде или микросервисах). Это делают через exception_handler.

    Используй это умеренно: слишком агрессивная «перехватка всего» может скрывать реальные проблемы.

    Как это выглядит как проект, а не как один файл

    Чтобы связать с темой структуры проектов из предыдущей статьи, типичный минимальный каркас:

    Роли файлов:

  • main.py — создание FastAPI() и подключение роутов
  • api.py — маршруты
  • schemas.py — Pydantic-модели (контракты)
  • Это помогает:

  • избегать циклических импортов
  • держать доменную логику отдельно от HTTP
  • проще тестировать
  • Минимальный чеклист качества для REST API

    Перед тем как считать ручку готовой, проверь:

  • методы и пути соответствуют смыслу (GET не создаёт данные)
  • для POST создания используется 201
  • ошибки возвращаются через HTTPException с правильными кодами
  • входные данные валидируются моделями
  • ответ ограничен response_model
  • документация /docs отражает реальное поведение
  • Что важно вынести

  • HTTP — это контракт между клиентом и сервером: метод, путь, статус-код, тело, заголовки.
  • FastAPI использует типы и Pydantic-модели, чтобы автоматически валидировать ввод и генерировать документацию.
  • Ошибки должны быть предсказуемыми: HTTPException для ожидаемых ситуаций, аккуратное отношение к 5xx.
  • Структура проекта и разделение файлов делают API поддерживаемым и удобным для командной разработки.
  • 3. Базы данных и ORM: PostgreSQL, SQLAlchemy, миграции и транзакции

    Базы данных и ORM: PostgreSQL, SQLAlchemy, миграции и транзакции

    В прошлых статьях ты научился писать поддерживаемый Python-код и поднимать REST API на FastAPI с валидацией и понятными ошибками. Следующий обязательный шаг для трудоустройства backend-разработчиком: хранение данных в базе, работа через ORM и безопасное изменение схемы через миграции.

    В этой статье разберём:

  • PostgreSQL как основную базу данных для backend
  • SQLAlchemy как ORM и инструмент для запросов
  • Alembic для миграций
  • Транзакции и правила работы с ними в веб-приложении
  • Зачем backend-разработчику PostgreSQL

    PostgreSQL — популярная реляционная СУБД (система управления базами данных), которую часто ждут в вакансиях. Она умеет:

  • хранить данные в таблицах со строгой схемой
  • обеспечивать целостность данных через ограничения
  • выполнять сложные запросы эффективно
  • гарантировать корректность обновлений через транзакции
  • Официальная документация: PostgreSQL Documentation

    Реляционная модель простыми словами

    Реляционная БД хранит данные в таблицах.

  • Таблица — набор строк одного типа (например, пользователи)
  • Строка — один объект (например, один пользователь)
  • Колонка — поле (например, email)
  • Чтобы данные не превращались в хаос, применяют ограничения:

  • PRIMARY KEY — уникальный идентификатор строки
  • NOT NULL — поле обязательно
  • UNIQUE — значение должно быть уникальным
  • FOREIGN KEY — ссылка на строку в другой таблице
  • !Схема связи таблиц: один пользователь имеет много заказов

    Немного SQL, без которого не обойтись

    ORM не отменяет SQL. На собеседованиях и в работе тебя будут спрашивать и про запросы, и про индексы.

    Минимальный набор, который нужно уверенно понимать:

  • SELECT с WHERE
  • INSERT
  • UPDATE
  • DELETE
  • JOIN
  • ORDER BY, LIMIT, OFFSET
  • Пример запросов:

    Подключение к PostgreSQL

    Python-приложение общается с PostgreSQL через драйвер.

  • синхронный драйвер часто используют psycopg
  • асинхронный драйвер часто используют asyncpg
  • Официальные проекты:

  • psycopg
  • asyncpg
  • В реальных проектах доступ к БД почти всегда делают через SQLAlchemy, а драйвер выбирают как transport.

    ORM и почему она нужна

    ORM (Object-Relational Mapping) — слой, который связывает таблицы БД с объектами в коде.

    Что даёт ORM в backend:

  • меньше ручного SQL для типовых CRUD-операций
  • удобная работа со связями между таблицами
  • единый стиль доступа к данным
  • композиция с типизацией и Pydantic-моделями
  • При этом:

  • сложные выборки всё равно иногда удобнее писать как SQL или как SQLAlchemy Core-запрос
  • понимание SQL обязательно
  • SQLAlchemy: базовые понятия

    SQLAlchemy — стандарт де-факто для Python backend.

    Документация:

  • SQLAlchemy 2.0 Documentation
  • Ключевые термины:

  • Engine — объект, который знает, как подключаться к БД
  • Session — рабочая область для запросов и транзакций
  • Declarative model — Python-класс, который описывает таблицу
  • Unit of Work — принцип: изменения копятся в сессии и фиксируются commit() одной транзакцией
  • Модели: описываем таблицы через классы

    Ниже пример для SQLAlchemy 2.0. Он показывает типы, ограничения и связь один-ко-многим.

    Что важно:

  • unique=True на email гарантирует, что два пользователя с одним email не появятся
  • nullable=False делает поле обязательным
  • ForeignKey("users.id") фиксирует связь заказа с пользователем
  • relationship позволяет удобно ходить по связям в коде
  • Engine и Session: как выполняются запросы

    Синхронный вариант полезен для понимания и часто встречается в небольших проектах.

    Пояснение:

  • session.add() добавляет объект в отслеживание
  • commit() фиксирует транзакцию
  • refresh() перечитывает поля, которые могла заполнить БД (например, id)
  • Запросы в стиле SQLAlchemy 2.0

    В новых проектах чаще используют select().

    scalar() удобен, когда ожидается один объект или None.

    SQLAlchemy и FastAPI: жизненный цикл сессии

    В веб-приложении критично правило: одна сессия на один запрос.

    Почему:

  • транзакция должна иметь понятные границы
  • соединения с БД нельзя держать бесконечно
  • параллельные запросы не должны делить одну и ту же Session
  • FastAPI даёт удобный механизм зависимостей.

    Документация: FastAPI Dependencies

    Асинхронный вариант (часто встречается с FastAPI)

    Пример ручки:

    Что здесь важно для трудоустройства:

  • IntegrityError появляется при нарушении ограничений (например, UNIQUE)
  • после ошибки надо делать rollback(), иначе сессия остаётся в ошибочном состоянии
  • 409 Conflict подходит для ситуации «ресурс конфликтует с текущим состоянием»
  • Миграции: как безопасно менять схему БД

    Схема БД меняется постоянно: новые поля, таблицы, индексы. Делать это вручную на серверах опасно. Для этого используют миграции.

    Alembic — стандартный инструмент миграций для SQLAlchemy.

    Документация:

  • Alembic Documentation
  • Базовый рабочий процесс

  • Инициализировать Alembic в проекте.
  • Настроить URL базы и подключение моделей.
  • Создать миграцию.
  • Применить миграцию.
  • Команды выглядят примерно так:

    Что означает:

  • revision создаёт файл миграции
  • --autogenerate пытается сравнить модели SQLAlchemy с текущей схемой БД
  • upgrade head применяет все миграции до последней
  • Практическое правило:

  • автогенерация экономит время
  • но миграцию нужно читать и проверять, особенно при удалении колонок и таблиц
  • Что обычно добавляют миграциями

  • новые таблицы
  • новые колонки
  • NOT NULL ограничения
  • индексы
  • UNIQUE ограничения
  • Индексы важны для производительности.

  • если ты часто ищешь пользователя по email, индекс или UNIQUE на email обязателен
  • Справка по индексам в PostgreSQL: PostgreSQL Indexes

    Транзакции: что это и почему без них нельзя

    Транзакция — это группа операций, которая выполняется как единое целое.

    Если упрощать, транзакция даёт два ключевых свойства:

  • либо применятся все изменения, либо не применится ничего
  • параллельные операции не должны ломать целостность данных
  • В PostgreSQL транзакции описаны здесь: PostgreSQL Transactions

    Где транзакции в SQLAlchemy

  • session.commit() завершает транзакцию успешно
  • session.rollback() откатывает изменения
  • Главная ошибка новичков: сделать несколько связанных изменений и фиксировать частями.

    Пример задачи: создать заказ и списать бонусы пользователя. Это должно быть в одной транзакции.

    Контекст транзакции

    Синхронно:

    Асинхронно:

    Плюсы begin():

  • если внутри блока возникла ошибка, произойдёт rollback()
  • если всё хорошо, произойдёт commit()
  • !Жизненный цикл транзакции внутри одного HTTP-запроса

    Какие ошибки часто связаны с транзакциями

  • забыли сделать rollback() после исключения
  • делали commit() слишком рано, а потом упали на середине бизнес-операции
  • держали транзакцию открытой слишком долго (например, делали внешние HTTP-вызовы внутри транзакции)
  • Правило для практики:

  • внутри транзакции делай только работу с БД
  • внешние запросы, тяжёлые вычисления и ожидания лучше выносить за границы транзакции
  • Как связать Pydantic-модели и ORM-модели

    В FastAPI удобно разделять:

  • ORM-модели SQLAlchemy: как данные хранятся в БД
  • схемы Pydantic: что принимает и отдаёт API
  • Пример:

    Такое разделение полезно, потому что:

  • API-контракт не обязан совпадать со структурой таблиц
  • ты контролируешь, какие поля отдаёшь наружу
  • проще поддерживать версионирование API
  • Минимальный чеклист для проекта с БД

    | Тема | Что должно быть в проекте | Почему это важно | |---|---|---| | Подключение | engine и sessionmaker | единый способ работы с БД | | Сессии | одна сессия на один запрос | безопасность и предсказуемость | | Модели | ограничения NOT NULL, UNIQUE, FK | целостность данных | | Ошибки | обработка IntegrityError | корректные ответы API | | Миграции | Alembic, автогенерация и проверка | воспроизводимость схемы | | Транзакции | begin() для бизнес-операций | атомарность изменений |

    Что важно вынести

  • PostgreSQL — стандартная реляционная БД для backend, ограничения и индексы в ней так же важны, как и код.
  • SQLAlchemy даёт ORM и удобный способ писать запросы, но SQL понимать всё равно нужно.
  • В FastAPI почти всегда делают одну сессию на один HTTP-запрос.
  • Alembic решает проблему безопасных изменений схемы: миграции должны быть воспроизводимыми.
  • Транзакции — ключ к целостности данных: связанные изменения фиксируются вместе, ошибки откатываются через rollback().
  • 4. Качество и безопасность: тесты, логирование, конфигурация, аутентификация

    Качество и безопасность: тесты, логирование, конфигурация, аутентификация

    В предыдущих темах ты научился:

  • писать поддерживаемый Python-код (ООП, типы, структура проекта)
  • делать REST API на FastAPI (маршруты, валидация, ошибки)
  • подключать PostgreSQL через SQLAlchemy, использовать миграции и транзакции
  • Теперь важный шаг к реальному продакшену и трудоустройству: качество и безопасность. На практике тебя будут оценивать не только по тому, что API “работает”, но и по тому, что его можно:

  • безопасно запускать в разных окружениях (dev, staging, prod)
  • диагностировать по логам
  • покрывать тестами без ручной проверки
  • защищать от несанкционированного доступа
  • Тесты: как доказать, что API работает и не ломается

    Тесты в backend решают две задачи:

  • защищают от регрессий при изменениях
  • ускоряют разработку, потому что ты быстрее получаешь обратную связь
  • Самый популярный стек в Python:

  • pytest как тестовый раннер
  • тестирование FastAPI через TestClient (или httpx для async)
  • отдельная тестовая база данных
  • Ссылки:

  • pytest
  • FastAPI Testing
  • HTTPX
  • pytest-asyncio
  • Какие тесты чаще всего пишут в backend

    Удобная модель, которую ждут на работе:

  • unit-тесты для чистой бизнес-логики (без HTTP и БД)
  • integration-тесты для слоя БД (реальные запросы, транзакции)
  • API-тесты для ручек (HTTP + валидация + ошибки)
  • Важно: в учебных проектах часто пытаются тестировать только ручки. На работе ценится, когда бизнес-логика вынесена из HTTP-слоя, и её можно тестировать быстро.

    Unit-тест: тестируем бизнес-правило без FastAPI

    Пример правила: нельзя списать больше денег, чем есть на счёте.

    Плюс такого теста: он запускается быстро и не зависит от окружения.

    API-тест FastAPI: проверяем статус-коды и формат ответа

    FastAPI позволяет тестировать приложение как “чёрный ящик”: делаем запрос и проверяем ответ.

    Что это проверяет:

  • контракт HTTP (код ответа)
  • JSON-структуру ответа
  • Тестирование БД: изоляция и повторяемость

    Для трудоустройства важно понимать принцип:

  • тесты не должны зависеть от результатов предыдущих тестов
  • Практики изоляции:

  • перед каждым тестом создавать данные заново
  • откатывать транзакцию после теста
  • использовать отдельную тестовую БД
  • Если у тебя SQLAlchemy + FastAPI, обычно делают dependency override для тестовой сессии.

    Ссылка: FastAPI Dependencies

    Пример идеи (упрощённо):

    Главное, что нужно усвоить: FastAPI позволяет подменять зависимости, а значит тесты можно сделать стабильными.

    Логирование: как видеть, что происходит в продакшене

    В реальном backend print почти не используют, потому что:

  • нет уровней важности
  • сложно собирать и фильтровать
  • неудобно искать контекст ошибок
  • Стандартный инструмент в Python: модуль logging.

    Ссылка: logging

    Базовая настройка логов

    Минимально полезная конфигурация:

    Что логировать в backend

    Полезные правила:

  • логируй старт и итог критичных операций
  • логируй ошибки с контекстом (идентификаторы, параметры)
  • не логируй секреты (пароли, токены, ключи)
  • Для HTTP полезно иметь:

  • request_id (идентификатор запроса)
  • user_id (если есть аутентификация)
  • результат (статус-код)
  • !Диаграмма показывает, где в запросе появляются логи и контекст

    Обработка ошибок и logger.exception

    Когда ловишь неожиданную ошибку, полезно логировать стек вызовов:

    logger.exception автоматически добавляет traceback. Это помогает находить причины 500.

    Конфигурация: как управлять настройками без хардкода

    Одна из частых проблем джун-проектов: пароли, адреса БД и секреты “зашиты” в код.

    Правило продакшена:

  • конфигурация приходит из окружения (переменные окружения, секрет-хранилища)
  • код не содержит паролей и ключей
  • Что обычно относится к конфигурации

    Типичные настройки backend-приложения:

  • DATABASE_URL
  • APP_ENV (dev или prod)
  • LOG_LEVEL
  • SECRET_KEY
  • настройки токенов (время жизни)
  • Pydantic Settings: удобный способ описать конфигурацию типами

    Если ты уже использовал Pydantic-модели в FastAPI, то логично применить похожий подход к настройкам.

    Ссылка: Pydantic Settings

    Пример:

    Что это даёт:

  • типы помогают не допустить “битую” конфигурацию
  • централизованное место для настроек
  • .env удобен в локальной разработке
  • Режимы dev и prod

    Типичная схема:

  • в dev разрешён --reload, больше логов, проще диагностика
  • в prod меньше подробностей, строгие настройки, секреты только через окружение
  • Важно: не путай “удобно разрабатывать” и “безопасно запускать”.

    Аутентификация: как ограничить доступ к API

    Аутентификация отвечает на вопрос: “кто ты?”.

    Авторизация отвечает на вопрос: “что тебе можно?”.

    Вакансии backend почти всегда требуют базовый уровень понимания обеих.

    Способы аутентификации в HTTP

    Самые частые варианты:

  • HTTP Basic (почти не используют для продакшена как основную схему)
  • cookie-based сессии
  • Bearer token (часто JWT)
  • FastAPI имеет встроенные инструменты безопасности.

    Ссылка: FastAPI Security

    Пароли: как хранить правильно

    Пароли нельзя хранить в открытом виде. В БД хранят только хэш.

    Библиотека, которую часто используют в Python:

  • passlib
  • Идея:

  • при регистрации хэшируешь пароль
  • при входе проверяешь пароль через проверку хэша
  • Пример (упрощённо):

    Bearer token и JWT: популярная схема для API

    JWT часто используют как токен доступа.

    Библиотека: PyJWT

    FastAPI даёт готовые примитивы, например OAuth2PasswordBearer, чтобы извлекать токен из заголовка Authorization: Bearer ....

    Пример зависимости “требуется токен”:

    Использование в ручке:

    Какие статус-коды связаны с доступом

    Важно отвечать корректными кодами:

  • 401 Unauthorized если пользователь не аутентифицирован (нет токена, токен невалиден)
  • 403 Forbidden если пользователь аутентифицирован, но прав недостаточно
  • Минимальные правила безопасности для учебного проекта, близкого к продакшену

    Практичный набор привычек:

  • секреты и пароли только через окружение
  • пароли в БД только как хэш
  • токены проверяются в зависимости FastAPI
  • ошибки аутентификации всегда дают 401 или 403, а не 500
  • в логах нет паролей и токенов
  • Как связать всё в один “боевой” каркас проекта

    Пример структуры, которая логично продолжает темы FastAPI и SQLAlchemy:

    Роли компонентов:

  • config.py читает окружение и типизирует настройки
  • logging_config.py включает формат и уровни логов
  • db.py даёт engine и get_session как зависимость
  • api/auth.py отвечает за логин и токены
  • tests/ проверяет бизнес-правила, ручки, статусы и ошибки
  • Что важно вынести

  • Тесты в backend делятся на unit, integration и API: они ускоряют развитие и защищают от регрессий.
  • Логи в продакшене важнее print: нужны уровни, контекст и безопасное содержание.
  • Конфигурация должна быть вынесена из кода в окружение, а типизация настроек помогает ловить ошибки рано.
  • Аутентификация и безопасное хранение паролей это обязательный минимум для реального API.
  • 5. Продакшн и портфолио: Docker, CI/CD, деплой, документация и проект

    Продакшн и портфолио: Docker, CI/CD, деплой, документация и проект

    В предыдущих статьях ты собрал основу backend-навыков: Python как инженерный инструмент, REST API на FastAPI, PostgreSQL + SQLAlchemy + миграции, тесты, логирование, конфигурация и аутентификация. Теперь финальный уровень, который отличает учебный проект от проекта, с которым реально можно идти на собеседования: как упаковать приложение, автоматически проверить качество, задеплоить и красиво представить в портфолио.

    Эта статья про практику “как в компании”:

  • Docker для воспроизводимой среды
  • CI (проверки в репозитории) и базовый CD (деплой)
  • деплой на хостинг
  • документация (OpenAPI + README)
  • как оформить итоговый проект в портфолио
  • !Общая картина CI/CD и деплоя для backend

    Что значит “готово для продакшена” на джун-уровне

    На джун-позиции от тебя обычно не ждут сложной инфраструктуры, но ждут, что ты понимаешь базовые инженерные свойства сервиса.

    Минимальный чеклист:

  • приложение запускается одинаково у тебя и у проверяющего
  • конфигурация берётся из окружения, секреты не лежат в коде
  • есть миграции и понятный способ поднять БД
  • есть тесты и они запускаются автоматически в CI
  • есть логи и понятный health endpoint
  • документация доступна и актуальна
  • Docker: воспроизводимый запуск приложения

    Docker позволяет упаковать приложение и зависимости в образ, чтобы запуск был повторяемым.

    Официальные источники:

  • Docker Documentation
  • Dockerfile reference
  • Docker Compose overview
  • Почему Docker важен для трудоустройства

    Docker решает типовую проблему “у меня работало локально”. Для портфолио это особенно критично: проверяющий должен поднять проект одной командой.

    Рекомендуемая структура проекта под портфолио

    Если ты следовал прошлым темам (FastAPI, SQLAlchemy, тесты), удобно держаться примерно такой структуры:

    Dockerfile для FastAPI

    Ниже минимальный production-friendly Dockerfile: кэширование зависимостей, запуск через uvicorn.

    Документация сервера:

  • Uvicorn
  • Если у тебя нет requirements.txt, выбери один из подходов и придерживайся его в проекте:

  • pip-tools и requirements.txt
  • Poetry
  • uv
  • Важнее не инструмент, а воспроизводимость.

    .dockerignore

    dockerignore ускоряет сборку и не тащит лишнее в образ.

    Docker Compose: приложение + PostgreSQL

    В портфолио почти всегда полезно дать docker-compose.yml, чтобы поднять сервис и базу одной командой.

    Документация:

  • PostgreSQL Docker image
  • Команда запуска:

    Миграции в Docker-процессе

    Из прошлой статьи ты знаешь, что схема должна быть воспроизводима миграциями (Alembic).

    Документация:

  • Alembic Documentation
  • Практичный вариант для портфолио:

  • Поднять db и api
  • Отдельной командой применить миграции внутри контейнера
  • Это проще, чем пытаться автоматически мигрировать при каждом старте (в реальном продакшене это решение принимают осторожно).

    CI/CD: автоматические проверки и доставка

    CI (Continuous Integration) это автоматические проверки на каждый push или pull request.

    CD (Continuous Delivery/Deployment) это автоматическая доставка: сборка образа, публикация, деплой.

    Официальные источники:

  • GitHub Actions Documentation
  • Что стоит включить в CI для backend-проекта

    Минимальный CI-пайплайн для трудоустройства:

  • ruff как линтер
  • black как форматтер (проверка, а не автоисправление)
  • mypy для типов
  • pytest для тестов
  • Ссылки:

  • Ruff
  • Black
  • mypy
  • pytest
  • Пример GitHub Actions workflow

    Создай файл .github/workflows/ci.yml:

    Если в тестах есть реальная БД, добавь сервис PostgreSQL в workflow. Для портфолио часто достаточно unit-тестов и тестов ручек без БД, но если ты умеешь поднимать тестовую БД в CI, это сильный плюс.

    Pre-commit: чтобы не ждать CI

    CI должен быть “последним барьером”, но удобнее ловить ошибки до коммита.

    Документация:

  • pre-commit
  • Суть:

  • ты ставишь хуки один раз
  • при коммите автоматически прогоняются форматтер и линтер
  • Деплой: как показать проект живым

    Для портфолио важно не только “код на GitHub”, но и живой URL.

    Варианты деплоя для джун-уровня:

  • PaaS платформы (проще): Render, Fly.io, Railway
  • VPS (сложнее, но полезно): Ubuntu сервер + Docker + reverse proxy
  • Выбирай то, что ты сможешь стабильно поддерживать и объяснить.

    Что нужно для деплоя FastAPI

    Технический минимум:

  • команда запуска приложения
  • переменные окружения (включая DATABASE_URL и SECRET_KEY)
  • база данных (управляемая на платформе или отдельная)
  • миграции (вручную или отдельной задачей)
  • Официальная рекомендация по продакшен-развёртыванию FastAPI:

  • FastAPI Deployment
  • Health endpoint

    Для диагностики и мониторинга добавь endpoint здоровья, если его ещё нет.

    Проверяющий сможет быстро понять, что сервис поднялся.

    Конфигурация и секреты

    Свяжи с прошлой статьёй: настройки должны быть в окружении, а не в коде.

    Практика:

  • добавь .env.example с названиями переменных
  • не коммить .env
  • на платформе задай переменные окружения через UI
  • Документация для подхода “конфигурация через окружение” хорошо отражена в идеях 12-factor:

  • The Twelve-Factor App
  • Документация: OpenAPI, README и примеры запросов

    В портфолио документация решает половину задачи: она показывает, что ты умеешь делать контракт и думать о пользователе API.

    OpenAPI в FastAPI

    FastAPI автоматически строит схему и UI:

  • GET /docs (Swagger UI)
  • GET /redoc (ReDoc)
  • Документация:

  • FastAPI OpenAPI
  • Требования к портфолио-проекту:

  • ручки должны быть типизированы
  • входные данные должны быть Pydantic-моделями
  • ответы желательно фиксировать через response_model
  • ошибки должны быть оформлены через HTTPException с правильными статусами
  • README: как сделать так, чтобы проектом захотели воспользоваться

    README должен отвечать на вопросы проверяющего без “созвона”.

    Рекомендуемый план README:

  • Что это за сервис: 2–4 предложения
  • Фичи: список возможностей
  • Стек: FastAPI, PostgreSQL, SQLAlchemy, Alembic, Docker, pytest
  • Как запустить локально: команды
  • Как прогнать тесты и линтеры: команды
  • Переменные окружения: описание DATABASE_URL, SECRET_KEY и т.д.
  • Ссылки: URL деплоя и /docs
  • Примеры запросов

    Добавь несколько примеров для Postman или curl.

    Если есть аутентификация:

    Итоговый проект для портфолио: что собирать

    Нужен проект, который демонстрирует весь курс как единую систему.

    Вариант проекта: мини-сервис задач

    Функциональность, которая выглядит убедительно и не слишком огромная:

  • регистрация и логин
  • создание задач
  • изменение статуса задачи
  • фильтрация и пагинация списка задач
  • права доступа: пользователь видит только свои задачи
  • Стек, который ты уже проходил:

  • FastAPI
  • Pydantic
  • PostgreSQL
  • SQLAlchemy
  • Alembic
  • pytest
  • logging
  • Docker + Compose
  • CI на GitHub Actions
  • Минимальный набор ручек

    Примерный набор:

  • POST /auth/register
  • POST /auth/token
  • GET /me
  • POST /tasks
  • GET /tasks
  • PATCH /tasks/{task_id}
  • DELETE /tasks/{task_id}
  • Что особенно ценится на собеседованиях

    Ниже вещи, которые часто “поднимают” учебный проект до уровня, когда его реально интересно обсуждать.

  • корректные статус-коды (201, 204, 401, 403, 404, 409, 422)
  • обработка конфликтов на уровне БД (например, UNIQUE) и перевод в HTTP-ошибку
  • транзакции вокруг бизнес-операций
  • изоляция тестов и dependency override в FastAPI
  • логирование без утечек секретов
  • Docker Compose для локального запуска
  • CI, который падает при проблемах
  • Финальный чеклист “перед отправкой работодателю”

    Проверь проект как продукт:

  • docker compose up --build поднимает сервис и БД
  • есть понятная команда для применения миграций
  • pytest проходит локально и в CI
  • ruff, black --check, mypy проходят локально и в CI
  • .env.example есть, .env не в репозитории
  • /docs открывается на деплое
  • README объясняет запуск за 3–5 минут
  • Что важно вынести

  • Docker и Compose превращают твой проект в воспроизводимый сервис.
  • CI через GitHub Actions делает качество проверяемым и привычным для командной работы.
  • Деплой и живой URL усиливают портфолио сильнее, чем “просто код”.
  • Документация это часть API-контракта: /docs плюс понятный README.
  • Итоговый проект должен демонстрировать полный цикл: HTTP, валидация, БД, миграции, безопасность, тесты, логи, конфигурация, деплой.