По шагам:
- Шаг 1. Создание структуры проекта и
main.py - Шаг 2. Добавление
models.py+ использование модели вmain.py - Шаг 3. Добавление
config.py+ переменные окружения + обновлениеmain.py - Шаг 4. Добавление
logger.py+ интеграция логгера - Шаг 5. Создание
.envи его чтение - Шаг 6. Добавление линтеров и форматтеров: black, flake8, isort
- Шаг 7. Подключение pre-commit + пояснение для Windows и PowerShell
fastapi_project/
├── app/
│ ├── __init__.py
│ └── main.py
├── requirements.txt
Открой VSCode, открой терминал (Ctrl + ~) и выполни:
mkdir fastapi_project
cd fastapi_project
python -m venv venv
.\venv\Scripts\Activate.ps1 # Активируем виртуальное окружение в PowerShellТеперь ты должен видеть что-то вроде:
(venv) PS C:\...\fastapi_project> — это значит окружение работает.
Создай файл requirements.txt в корне проекта:
📄 requirements.txt
fastapi
uvicorn[standard]
Установи зависимости:
pip install -r requirements.txtmkdir app
ni app\main.py
ni app\__init__.pyfrom fastapi import FastAPI
# Создаем экземпляр приложения FastAPI
app = FastAPI()
# Простейший маршрут
@app.get("/")
def read_root():
return {"message": "Hello, FastAPI!"}Запуск в PowerShell из корня проекта:
uvicorn app.main:app --reloadapp.main— путь до файлаapp/main.pyapp— объект FastAPI внутри файла--reload— сервер будет перезапускаться при изменении кода
Перейди в браузере по адресам:
- http://localhost:8000 — ответ API
- http://localhost:8000/docs — Swagger-документация
- http://localhost:8000/redoc — альтернативная документация
- У тебя есть минимальный рабочий FastAPI проект
- Он запускается через Uvicorn
- Есть один GET-эндпоинт
/
- Создаём файл
models.py - Определяем Pydantic-модель
User - Обновляем
main.py— добавим POST-эндпоинт, который принимает JSON и возвращает его обратно - Протестируем через Swagger
fastapi_project/
├── app/
│ ├── __init__.py
│ ├── main.py
│ └── models.py 👈 Новый файл
├── requirements.txt
Если в терминале:
ni app\models.pyfrom pydantic import BaseModel
# Модель для POST-запроса
class User(BaseModel):
username: str
message: strПояснение:
BaseModel— базовый класс Pydantic- FastAPI будет использовать эту модель для валидации входящего JSON
- Если поля отсутствуют или неверного типа — автоматически вернётся 422 ошибка
Добавим POST-эндпоинт:
from fastapi import FastAPI
from app.models import User # 👈 Импорт модели
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello, FastAPI!"}
@app.post("/")
async def create_user(user: User):
"""
Пример приёма JSON через POST-запрос.
Данные автоматически валидируются Pydantic.
"""
return {
"username": user.username,
"message": user.message,
"status": "Received successfully ✅"
}uvicorn app.main:app --reloadПерейди по адресу: 👉 http://localhost:8000/docs
Найди раздел POST / → нажми “Try it out”
Пример тела запроса:
{
"username": "Vasya",
"message": "I am Batman"
}Ты должен получить ответ:
{
"username": "Vasya",
"message": "I am Batman",
"status": "Received successfully ✅"
}- У тебя есть Pydantic-модель
User - Она используется в POST-запросе по пути
/ - Валидация работает автоматически
- Можно тестировать прямо из браузера через Swagger
На этом этапе ты:
- Создашь
.envфайл с настройками - Добавишь
config.py, который будет безопасно читать переменные окружения - Подключишь эту конфигурацию в
main.py(например, чтобы отобразитьDATABASE_URL)
fastapi_project/
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── models.py
│ └── config.py 👈 Новый файл
├── .env 👈 Новый файл
├── requirements.txt
Это удобный способ работать с .env файлами (альтернатива python-dotenv).
pip install environsИ обязательно добавь в requirements.txt:
environsСоздай файл .env в корне (рядом с requirements.txt).
Можно через терминал:
ni .envИ добавь туда следующее:
DATABASE_URL=sqlite:///./test.db
SECRET_KEY=my_super_secret_key
DEBUG=Truefrom dataclasses import dataclass
from environs import Env
# Конфиг для БД
@dataclass
class DatabaseConfig:
database_url: str
# Общая конфигурация проекта
@dataclass
class Config:
db: DatabaseConfig
secret_key: str
debug: bool
# Функция загрузки из .env
def load_config(path: str = None) -> Config:
env = Env()
env.read_env(path) # Загружаем переменные окружения из .env
return Config(
db=DatabaseConfig(
database_url=env("DATABASE_URL")
),
secret_key=env("SECRET_KEY"),
debug=env.bool("DEBUG", default=False)
)Теперь обновим main.py, чтобы использовать конфигурацию:
from fastapi import FastAPI
from app.models import User
from app.config import load_config # 👈 Импортируем конфигурацию
app = FastAPI()
# Загружаем конфиг
config = load_config()
@app.get("/")
def read_root():
return {"message": "Hello, FastAPI!"}
@app.post("/")
async def create_user(user: User):
return {
"username": user.username,
"message": user.message,
"status": "Received successfully ✅"
}
@app.get("/db")
def get_db_info():
"""
Возвращает строку подключения к БД из переменной окружения
"""
return {"db_url": config.db.database_url}uvicorn app.main:app --reloadПерейди по адресу:
Ты должен увидеть:
{
"db_url": "sqlite:///./test.db"
}- Переменные хранятся в
.envи не захардкожены - Все настройки централизованы в
config.py main.pyчитает эти переменные черезload_config()- Ты можешь легко переключаться между dev/prod-режимами через
.env
На этом шаге:
- Создаём файл
logger.pyс настройкой логирования - Подключаем его в
main.py - Добавим логирование действий (например, POST-запросов)
fastapi_project/
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── models.py
│ ├── config.py
│ └── logger.py 👈 Новый файл
├── .env
├── requirements.txt
Создай файл через PowerShell:
ni app\logger.pyДобавь код:
import logging
def setup_logger():
# Создаем объект логгера
logger = logging.getLogger("my_app")
logger.setLevel(logging.DEBUG) # Уровень логирования (можно INFO/ERROR/WARNING)
# Создаем консольный обработчик
ch = logging.StreamHandler()
ch.setLevel(logging.DEBUG)
# Формат сообщений
formatter = logging.Formatter(
"%(asctime)s - %(name)s - %(levelname)s - %(message)s"
)
ch.setFormatter(formatter)
# Добавляем обработчик к логгеру
logger.addHandler(ch)
return logger
# Глобальный логгер для импорта
logger = setup_logger()Теперь добавим логгер:
from fastapi import FastAPI
from app.models import User
from app.config import load_config
from app.logger import logger # 👈 Импортируем логгер
app = FastAPI()
config = load_config()
@app.get("/")
def read_root():
logger.info("GET / — Hello message отправлен")
return {"message": "Hello, FastAPI!"}
@app.post("/")
async def create_user(user: User):
logger.info(f"POST / — получены данные от пользователя: {user.username}")
return {
"username": user.username,
"message": user.message,
"status": "Received successfully ✅"
}
@app.get("/db")
def get_db_info():
logger.debug("GET /db — возвращаем строку подключения к БД")
return {"db_url": config.db.database_url}uvicorn app.main:app --reloadЗайди на:
Сделай GET и POST-запросы. В терминале VSCode ты увидишь:
2025-07-04 10:25:34,102 - my_app - INFO - GET / — Hello message отправлен
2025-07-04 10:25:38,499 - my_app - INFO - POST / — получены данные от пользователя: Vasya
2025-07-04 10:25:42,341 - my_app - DEBUG - GET /db — возвращаем строку подключения к БД
- У тебя есть централизованный логгер
- Все важные события логируются в консоль
- Можно в будущем логировать в файл или отправлять в Sentry
На этом этапе:
- Подчистим и проверим
.env - Расширим его для продакшн/отладки
- Подтвердим, как
DEBUGиSECRET_KEYчитаются вmain.py - Добавим защиту от случайного запуска без
.env
fastapi_project/
├── app/
│ ├── __init__.py
│ ├── main.py
│ ├── models.py
│ ├── config.py
│ └── logger.py
├── .env ✅
├── requirements.txt
📄 .env
DATABASE_URL=sqlite:///./test.db
SECRET_KEY=my_super_secret_key
DEBUG=TrueТеперь в main.py мы можем использовать config.secret_key и config.debug.
from fastapi import FastAPI
from app.models import User
from app.config import load_config
from app.logger import logger
app = FastAPI()
config = load_config()
@app.get("/")
def read_root():
logger.info("GET / — Hello message отправлен")
return {
"message": "Hello, FastAPI!",
"debug": config.debug
}
@app.post("/")
async def create_user(user: User):
logger.info(f"POST / — получены данные от пользователя: {user.username}")
return {
"username": user.username,
"message": user.message,
"status": "Received successfully ✅",
"secret_key_used": config.secret_key
}
@app.get("/db")
def get_db_info():
logger.debug("GET /db — возвращаем строку подключения к БД")
return {
"db_url": config.db.database_url
}Обновим config.py — если .env не найден, отобразим понятное сообщение.
📄 app/config.py (добавим обработку ошибок):
from dataclasses import dataclass
from environs import Env
from pathlib import Path
@dataclass
class DatabaseConfig:
database_url: str
@dataclass
class Config:
db: DatabaseConfig
secret_key: str
debug: bool
def load_config(path: str = None) -> Config:
env = Env()
# Проверяем наличие .env файла
env_path = path or ".env"
if not Path(env_path).is_file():
raise FileNotFoundError(f"Файл {env_path} не найден. Создайте .env на основе документации.")
env.read_env(env_path)
return Config(
db=DatabaseConfig(
database_url=env("DATABASE_URL")
),
secret_key=env("SECRET_KEY"),
debug=env.bool("DEBUG", default=False)
)Теперь, если .env нет — приложение не стартует и пишет ошибку вроде:
FileNotFoundError: Файл .env не найден. Создайте .env на основе документации.Запусти приложение:
uvicorn app.main:app --reloadИ открой:
- GET
/— покажетdebug: true - POST
/— вернётsecret_key_used - GET
/db— покажетdb_url
- Все конфиги читаются централизованно
.envфайл — обязательный и контролируемый- FastAPI читает переменные как из настроек продакшна
На этом шаге ты:
- Установишь
black,flake8,isort - Создашь конфигурационные файлы
- Научишься запускать форматирование кода вручную в PowerShell
- Убедишься, что твой код соответствует стилю
fastapi_project/
├── app/
│ ├── main.py
│ ├── models.py
│ ├── config.py
│ └── logger.py
├── .env
├── requirements.txt
├── .black ✅
├── .flake8 ✅
├── .isort.cfg ✅
pip install black flake8 isortДобавь в requirements.txt (в конце):
black
flake8
isort
ni .blackСодержимое:
[tool.black]
line-length = 120
target-version = ['py311'] # замените на свою версию Python
extend-exclude = '''
(
venv
| alembic
| docker
| __pycache__
| .git
)
'''ni .flake8Содержимое:
[flake8]
exclude = __init__.py,venv,alembic,docker,.git,__pycache__
max-line-length = 120
ignore = E203, E266, E501, W503ni .isort.cfgСодержимое:
[tool.isort]
profile = black
[settings]
# include_trailing_comma = true # тут выдает ошибку
line_length = 120
lines_after_imports = 2
skip = __init__.py,venv,alembic,docker,.git,__pycache__Важно: Запускай из корня проекта
black --config .black .flake8 --config .flake8 .isort --settings-file .isort.cfg .| Инструмент | Что делает |
|---|---|
black |
Форматирует код автоматически |
flake8 |
Проверяет стиль, длину строк, ошибки |
isort |
Сортирует импорты, приводит к единому стилю |
Попробуй сделать намеренно плохо отформатированный импорт в main.py:
from fastapi import FastAPI
from app.models import User
from app.config import load_config
from app.logger import logger
import os,sysЗатем запусти:
isort --settings-file .isort.cfg .
black --config .black .
flake8 --config .flake8 .Ошибки будут найдены и/или автоматически исправлены.
- Твой проект теперь можно проверять и форматировать перед каждым коммитом
- Все инструменты конфигурируются отдельно
- Ты знаешь, как запускать их вручную в PowerShell
На этом шаге ты:
- Установишь и настроишь
pre-commit - Создашь
.pre-commit-config.yaml - Добавишь удобный скрипт
pre-commit - Подключишь хуки к Git
- Проверишь, что линтеры запускаются автоматически при коммите
fastapi_project/
├── app/
├── .env
├── requirements.txt
├── .black
├── .flake8
├── .isort.cfg
├── .pre-commit-config.yaml ✅
├── pre-commit ✅
pip install pre-commitИ добавь в requirements.txt:
pre-commit
ni .pre-commit-config.yamlСодержимое:
repos:
- repo: local
hooks:
- id: isort
name: isort
entry: isort --settings-file ./.isort.cfg .
args: ["--profile", "black"]
language: system
types: [python]
pass_filenames: false
- id: black
name: black
entry: black --config ./.black .
language: system
types: [python]
pass_filenames: false
- id: flake8
name: flake8
entry: flake8 --config .flake8 .
language: system
types: [python]
pass_filenames: false
⚠️ На Windows PowerShell этот файл ты можешь создать как обычный.ps1или.bat, но проще просто запускать команды вручную (см. ниже)
Создай обычный pre-commit скрипт:
ni pre-commitСодержимое:
isort --settings-file ./.isort.cfg .
black --config ./.black .
flake8 --config .flake8 .Для запуска вручную на Windows:
bash pre-commit # если установлен Git BashЛибо просто напрямую:
isort --settings-file ./.isort.cfg .
black --config ./.black .
flake8 --config .flake8 .Перейди в терминал (в корне проекта) и выполни:
pre-commit installПосле этого перед каждым коммитом автоматически будут запускаться isort, black, flake8.
- Измени любой
.pyфайл и сделай некрасивый код (например, добавь лишние пробелы или неотсортированные импорты) - Сделай git-коммит:
git add .
git commit -m "Test pre-commit"В консоли ты увидишь как запускаются проверки:
[INFO] Installing environment for local.
[INFO] Once installed this environment will be reused.
isort...........................................(passed/rewritten)
black...........................................(passed/rewritten)
flake8..........................................(passed)
- Все линтеры автоматически запускаются перед коммитом
- Проект поддерживается в чистоте без ручной возни
- Конфигурация сохранена и будет работать у всех, кто клонирует репозиторий