Практика 1.3. Миграции, ENV, GitIgnore и структура проекта
Для выполнения лабораторной и всех практических работ рекомендуется использовать версию Python 3.10+
Миграции. Alembic
При разработке проекта может возникнуть потребность добавлять новые таблицы или изменять уже существующие. Ввиду того, что ORM SQLModel (и, следовательно, SQLAlchemy) не предусматривает встроенный механизм миграций, необходимо использовать готовые библиотеки позволяющие безопасно вносить изменения в таблицы и БД проекта.
В официальной документации к FastAPI рекомендуется использовать Alembic в качестве библиотеки для менеджмента изменений в базе данных. Эта библиотека разработана специально для ORM SQLAlchemy, и совместима с SQLModel. Подробнее можно прочитать на официальном сайте.
Для интеграции Alembic в разрабатываемый проект необходимо его установить через пакетный менеджер:
Реализация механизма миграций происходит через вызов alembic init [name]
в командной строке, где [name] — название
папки, хранящей настройки миграций. Сгенерируем папку с миграциями и сопутствующие файлы настроек:
Сгенерировалась папка migratgions
хранящая внутри себя папку с файлами миграций versions
,
файл окружения БД env.py
и шаблон генерации миграций script.py.mako
. В корне проекта добавился файл настроек
alembic.ini
Для создания миграций в SQLModel необходимо добавить импорты моделей и настроить подключение к БД
-
В файле
alembic.ini
переменнойsqlalchemy.url
необходимо указать адрес БД, по аналогии с тем, что находится в файлеconnection.py
-
В файле
env.py
импортировать все изmodels.py
и в переменнойtarget_metadata
указать значениеtarget_metadata=SQLModel.metadata
Пример файла
from logging.config import fileConfig from sqlalchemy import engine_from_config from sqlalchemy import pool from alembic import context from models import * # this is the Alembic Config object, which provides # access to the values within the .ini file in use. config = context.config # Interpret the config file for Python logging. # This line sets up loggers basically. fileConfig(config.config_file_name) # add your model's MetaData object here # for 'autogenerate' support # from myapp import mymodel # target_metadata = mymodel.Base.metadata #target_metadata = None target_metadata = SQLModel.metadata # other values from the config, defined by the needs of env.py, # can be acquired: # my_important_option = config.get_main_option("my_important_option") # ... etc. def run_migrations_offline() -> None: """Run migrations in 'offline' mode. This configures the context with just a URL and not an Engine, though an Engine is acceptable here as well. By skipping the Engine creation we don't even need a DBAPI to be available. Calls to context.execute() here emit the given string to the script output. """ url = config.get_main_option("sqlalchemy.url") context.configure( url=url, target_metadata=target_metadata, literal_binds=True, dialect_opts={"paramstyle": "named"}, ) with context.begin_transaction(): context.run_migrations() def run_migrations_online() -> None: """Run migrations in 'online' mode. In this scenario we need to create an Engine and associate a connection with the context. """ connectable = engine_from_config( config.get_section(config.config_ini_section, {}), prefix="sqlalchemy.", poolclass=pool.NullPool, ) with connectable.connect() as connection: context.configure( connection=connection, target_metadata=target_metadata ) with context.begin_transaction(): context.run_migrations() if context.is_offline_mode(): run_migrations_offline() else: run_migrations_online()
-
В файле
script.py.mako
импортировать библиотекуsqlmodel
-
Добавить
level
поле моделиSkillWarriorLink
- Создать файл миграций с помощью команды
alembic revision --autogenerate -m "skill added"
- Применить миграции с помощью команды
alembic upgrade head
Увидеть полученные изменения можно просмотрев поля таблицы через pgAdmin. Файлы миграций хранятся в .migrations/versions.
Замечание
Использование библиотеки alembic и миграций предполагает их описание, как описываются коммиты в гите.
При создании файлов миграции рекомендуется писать полезную информацию об изменениях в соответствующей команде
после маркера -m
.
Переменные окружения и .gitignore
При разработке приложений часто необходимо хранить ключи и пароли от БД и различного АПИ, к которому обращается
сервер. В больших проектах часто используются специальные хранилища
типа Hashicorp Vault
или GitGub Secrets для
хранения подобной информации, но если разработка небольшая, то прятать важные данные можно посредством .env
файлов.
env-файлы - специальные файлы, имеющие которые .env
расширение. Служат для изоляции приложения от среды, где оно
запускается. Они не должны
индексироваться системами контроля версий т.к. хранят чувствительную информацию о проекте.
Внимание!
Не стоит путать env-файлы с venv
(Виртуальным окружением) языка Python
.gitignore
Такие файлы необходимо реализовывать с учетом используемой системы контроля версий. При использовании Git необходимо создать специальный .gitignore-файл, исключающий индексацию таких файлов при разработке проекта.
Замечание
.gitignore-файлы используются для исключения из индексации лишних элементов внутри файловой структуры системы, не только файлов с чувствительной информацией. Обычно, исключаются все файлы влияющие на окружение, IDE и файлы БД.
У gitignore-файлов довольно простой синтаксис, ознакомится с ним можно в документации. Обычно, для типовых проектов существуют готовые шаблоны подобных файлов - они легко ищутся через поисковые системы.
Пример подобного файла для FastAPI-проекта
Для исключения .env
файла необходимо создать .gitignore
файл и всписать в него строку "*.env
", таким
образом исключив все варианты расположения файлов с подобным расширением.
После того
.env
По аналогии с .gitignore
необходимо создать файл .env
в корне проекта и вписать туда переменную с чувствительными
данными. В случае описываемого проекта это URL базы данных:
Чтобы получить данные из такого файла можно воспользоваться пакетом python-dotenv, для этого его надо установить:
После установки, в файле connetion.py
адрес БД с использованием переменных окружения должен указываться
следующим образом:
Практическое задание
- Реализовать в своем проекте все улучшения, описанные в практике
- Разобраться как передать в alembic.ini URL базы данных с
помощью
.env
-файла и реализовать подобную передачу.