Описываем схему в sqlAlchemy
Для создания запросов с помощью SQLAlchemy необходимо описать схему базы данных с помощью специальных объектов: таблицы описываются с помощью sqlalchemy.Table и привязываются к реестру sqlalchemy.MetaData, который хранит всю метаинформацию о базе данных. К слову, реестр MetaData способен не только хранить описанную в Python метаинформацию, но и представлять реальное состояние базы данных в виде объектов SQLAlchemy. Эта возможность в том числе позволяет Alembic сравнивать состояния и генерировать код миграций автоматически. Кстати, у каждой базы данных своя схема именования constraints по умолчанию. Чтобы вы не тратили время на именование новых constraints или на воспоминания/поиски того, как назван constraint, который вы собираетесь удалить, SQLAlchemy предлагает использовать шаблоны именования naming conventions. Их можно определить в реестре MetaData
Создаем реестр MetaData и передаем в него шаблоны именования, а также описываем схему базы данных объектами SQLalchemy
Рисунок 12 – Описывание схемы SQLAlchemy
Рисунок 13 – Описывание схемы SQLAlchemy
Настраиваем Alembic
Когда схема базы данных описана, необходимо сгенерировать миграции, но для этого сначала нужно настроить Alembic.
Чтобы воспользоваться командой alembic, необходимо выполнить следующие шаги:
Установить пакет: pip install alembic
Инициализировать Alembic: cd analyzer && alembic init db/alembic.
Эта команда создаст файл конфигурации analyzer/alembic.ini и папку analyzer/db/alembic со следующим содержимым:
env.py — вызывается каждый раз при запуске Alembic. Подключает в Alembic реестр sqlalchemy.MetaData с описанием желаемого состояния БД и содержит инструкции по запуску миграций.
script.py.mako — шаблон, на основе которого генерируются миграции.
versions — папка, в которой Alembic будет искать (и генерировать) миграции.
Указать адрес базы данных в файле alembic.ini:
; analyzer/alembic.ini [alembic] sqlalchemy.url = postgresql://user:hackme@localhost/analyzer
Указать описание желаемого состояния базы данных (реестр sqlalchemy.MetaData), чтобы Alembic мог генерировать миграции автоматически:
# analyzer/db/alembic/env.py
from analyzer.db import schema
target_metadata = schema.metadata
Alembic настроен и им уже можно пользоваться, но в нашем случае такая конфигурация имеет ряд недостатков:
Утилита alembic ищет alembic.ini в текущей рабочей директории. Путь к alembic.ini можно указать аргументом командной строки, но это неудобно: хочется иметь возможность вызывать команду из любой папки без дополнительных параметров.
Чтобы настроить Alembic на работу с определенной базой данных, требуется менять файл alembic.ini. Гораздо удобнее было бы указать настройки БД переменной окружения и/или аргументом командной строки, например --pg-url.
Название утилиты alembic не очень хорошо коррелирует с названием нашего сервиса. Конечному пользователю было бы намного удобнее, если бы все исполняемые команды сервиса имели общий префикс, например analyzer-*
Обертка для решения этих проблем - analyzer/db/__main__.py:
Для обработки аргументов командной строки Alembic использует стандартный модуль argparse. Он позволяет добавить необязательный аргумент --pg-url со значением по умолчанию из переменной окружения ANALYZER_PG_URL.
main()
Рисунок 13 – Обработка аргументов Alembic
Путь до файла alembic.ini можно рассчитывать относительно расположения исполняемого файла, а не текущей рабочей директории пользователя.
Рисунок 14 – Простраивание пути до файла alebic.ini
Когда утилита для управления состоянием БД готова, ее можно зарегистрировать в setup.py как исполняемую команду с понятным конечному пользователю названием, например analyzer-db
Регистрация исполняемой команды в setup.py:
from setuptools import setup
setup(...,entry_points={'console_scripts':[
'analyzer-db = analyzer.db.__main__:main' ] })
После переустановки модуля будет сгенерирован файл env/bin/analyzer-db и команда analyzer-db станет доступной:
Рисунок 15 – Обертка Alembic