Найти в Дзене
Computer Pro

FasAPI + Postgres + Alembic + линтеры и тесты. GitHub actions (CI). Часть 1

Я долго ломал голову над названием данного цикла статей. Ничего умного в голову не пришло, поэтому перечислю всё что будет использовано в данном проекте. ЗЫ. Это не руководство к действию, не список рецептов, а что-то типа лайв-коддинга. Тут могут быть ошибки! Я просто пытаюсь упорядочить свои действия и размышления. Так что - "ПОНЯТЬ И ПРОСТИТЬ" Чот я подзавис на реализации домашнего задания связанного с CI. То одно не работает, то другое, то версии не совпадают, всё какая то ерунда получается и мой внутренний перфекционист кричит благим матом! Но и тянуть с завершением данного проекта уже некуда. В общем, захотелось сделать красиво. Но как оно получится в конце данной статьи я не знаю. Статья пишется в процессе написания приложения на FastAPI. Это будет приложение по управлению кулинарными рецептами. Со всеми плюшечками (файлом настроек, роуты будут размещены в отдельных файлах и т.д. и само-собой начальным файлом .env где будут тоже какие-то типа секретные данные). Приложение пишет
Оглавление

Я долго ломал голову над названием данного цикла статей. Ничего умного в голову не пришло, поэтому перечислю всё что будет использовано в данном проекте.

ЗЫ. Это не руководство к действию, не список рецептов, а что-то типа лайв-коддинга. Тут могут быть ошибки! Я просто пытаюсь упорядочить свои действия и размышления.
Так что - "ПОНЯТЬ И ПРОСТИТЬ"
Просто фото, для обложки карточки. Фото моё.
Просто фото, для обложки карточки. Фото моё.

Чот я подзавис на реализации домашнего задания связанного с CI. То одно не работает, то другое, то версии не совпадают, всё какая то ерунда получается и мой внутренний перфекционист кричит благим матом! Но и тянуть с завершением данного проекта уже некуда. В общем, захотелось сделать красиво. Но как оно получится в конце данной статьи я не знаю. Статья пишется в процессе написания приложения на FastAPI. Это будет приложение по управлению кулинарными рецептами. Со всеми плюшечками (файлом настроек, роуты будут размещены в отдельных файлах и т.д. и само-собой начальным файлом .env где будут тоже какие-то типа секретные данные).

Приложение пишется по мотивам этого видео:

Базовое приложение на FastAPI | Каркас проекта FastAPI + SQLAlchemy (ascynio) + alembic

Я так же как и автор этого видео буду пользоваться poetry (типа продвинутый pip, но я с ним знаком мало).

Начинаю с создания нового репозитория на гитхабе и соответственно клонирование этого свежесозданного репозитория в PyCharm'e. Создание нового виртуального окружения, создание файла .gitignore. Создаю директорию src/ в которой и будет располагаться весь проект.

Для работы с poetry в директории src/ нужно создать файл pyproject.toml, в котором будут следующие строки:

Для установки необходимых приложений нужны только эти строчки, далее будет установка и в этом файле будут появляться новые зависимости
Для установки необходимых приложений нужны только эти строчки, далее будет установка и в этом файле будут появляться новые зависимости

Открываем терминал, переходим в директорию с файлом pyproject.toml и запускаем установку зависимостей:

расширения standard и email для пакетов uvicorn и pydantic я скопировал из видео, и возможно они мне даже не понадобятся... ну да ладно, опыт приходит с практикой...
расширения standard и email для пакетов uvicorn и pydantic я скопировал из видео, и возможно они мне даже не понадобятся... ну да ладно, опыт приходит с практикой...

Зависимости установлены, можно создать файл main.py в котором и будет запускаться наше приложение.

-4

Можно вообще всё описать в файле main.py и это будет огромная "портянка" на много-много строк, в которой будет легко потеряться. Поэтому я буду делать проект, разложенный по логически правильным местам, так же как делают более продвинутые программисты. Хотя, порой, кажется что это тоже усложнение...

Все мало-мальские изменения буду фиксировать в GIT, дабы потом было проще проследить что и как я делал в данном проекте. Что называется "Слона надо есть по частям")))

-5

config.py

Начну с файла настроек src/core/config.py в котором и будут объявлены необходимые параметры в виде класса:

Создам файл .env в котором будут написаны настройки подключения к БД, которые не должны попасть в гит
Создам файл .env в котором будут написаны настройки подключения к БД, которые не должны попасть в гит
-7

После импортирования (from core.config import settings) экземпляра Settings(), в файле main.py исчезли ошибки:

-8

Можно приступать к следующему шагу - к реализации db_helper.

db_helper.py

Создаем файл src/core/models/db_helper.py. Данный файл будет создавать асинхронные движок и "фабрику" сессий, так же отвечать за выключение созданного движка подключения к БД, после выполнения всех операций.

-9
-10

Как можно видеть - необходимо установить sqlalchemy и asyncpg, установим:

-11

db_helper.py написан, проимпортирован в файле main.py, теперь можно переходить к написанию роутов, которые закроют ошибку:

-12

После чего можно будет попробовать запустить приложение.

Роуты...

Сначала хотел все роуты поместить в файл src/api/__init__.py дабы там все "проинклюдить" но чот не получается, отрабатывает только один роут - главный, остальные пропускает... Не знаю почему...

-13

Поэтому __init__.py был удалён за ненадобностью в данном проекте. А роуты рецептов и главной страницы были импортированы на главную main.py:

-14

Когда у тебя этих роутов не очень много (как в данном проекте), это еще куда ни шло, но если была бы сотня роутов - надо с этим что-то делать. Ибо main.py разрастется от импортов и инклюдов а это думаю не самый лучший вариант.

Оба файла src/api/main_page.py и src/api/recipes.py это пока просто заглушки, которые выводят заранее известное сообщение:

-15
-16

Если main_page.py это просто заглушка того чтобы обращение к главной не вызывало сообщения {"detail":"Not Found"}, а вот recipes.py будет отредактирован для работы с базой данных чуть далее.

Ну вот, первый запуск работающего приложения:

-17

При обращении к сваггеру (встроенная документация для FasAPI, находится по адресу http://127.0.0.1:8000/docs), можно теперь увидеть какие-то базовые роуты. И main.py теперь не подсвечивается ошибкой...

Ну и в заключении этого подпункта я пропишу pydantic schema, для главной страницы ибо некрасиво так:

что за стринг, непонятно!
что за стринг, непонятно!

Создал простенькую базовую модель:

-19

И подключил ее в файле роута главной страницы:

-20

И теперь ответ выглядит более внятно:

-21

Плюс, внизу появилась "схема":

-22

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

Подключение СУБД Postgresql к проекту

Казалось бы, у меня самый примитивный проект, можно бы и SQLite использовать, но не сейчас, просто тренировки ради. Да и автор ролика использовал Postgres.

Создаю простенький файл src/docker-compose.yaml, в котором и будет подтягиваться база данных:

-23

Поднимаем эту конструкцию:

-24
-25

Ну вот, приложение запущено, бд_шечка тоже, теперь надо попытаться сделать первый CRUD (Create, Read, Update, Delete) запрос. Но чтобы сделать запрос нужно наполнить базу данных таблицами и данными в эти таблицы.

Я собираюсь создавать таблицы и наполнять их данными при помощи миграций в alembic.

Установка alembic + black:

poetry add alembic black

Инициализация alembic:

alembic init -t async alembic

После установки, необходимо сконфигурировать alembic.ini, раскомментировать строчки:

-26
-27

Далее нужно отредактировать файл src/alembic/env.py:

-28

Базовый класс моделей у нас еще не создан, надо создать. Поэтому пока что я просто запишу импорты, settings у нас уже есть, а Base просто укажу откуда импортировать. А сам же пойду решать задачу по создании базовой и остальных моделей данного приложения.

-29

Но это уже история следующей части. Продолжение следует...

UPD: продожение