Миграции базы данных с помощью Alembic

Работа с базами данных – важная составляющая современного программирования. И очень важным аспектом взаимодействия с ними является миграция. Это что-то напоминающее систему контроля версий. Чтобы реализовать это на практике, используется Alembic – специализированный инструмент для миграции базы данных. Он применяется не самостоятельно, а внутри SQLAlchemy.

Начать надо с напоминания того, что в SQLAlchemy метод create_all() используется лишь для создания из моделей тех таблиц, которых не хватает. Если же она уже создана, то схема не изменяется. 

При разработке программы есть практика изменения схемы таблицы. Alembic здесь как раз и становится полезным. Точно так же, как и другие аналогичные инструменты, он дает возможность изменять схему базы данных, когда программа развивается. Он отслеживает изменения в базе данных. Поэтому нет необходимости в том, чтобы двигаться туда и обратно. Если не использовать Alembic, все придется отслеживать самостоятельно, что довольно затратно по ресурсам.

Чтобы наладить работу с Alembic во Flask, используется расширение Flask-Migrate. Чтобы установить расширение, необходимо ввести следующую команду. 

(env) gvido@vm:~/flask_app$  pip install flask-migrate

Чтобы связать Flask-Migrate с приложением, необходимо выполнить импорт классов Migrate и MigrateCommand из пакета flask_package. Помимо этого необходимо создать объект класса Migrate, передав экземпляр приложения и объект SQLAlchemy (db)

#...

from flask_migrate import Migrate, MigrateCommand

app = Flask(__name__)

app.debug = True

app.config['SECRET_KEY'] = 'a really really really really long secret key'

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:pass@localhost/flask_app_db'

manager = Manager(app)

db = SQLAlchemy(app)

migrate = Migrate(app,  db)

manager.add_command('db', MigrateCommand)

#...

С помощью класса MigrateCommand определяется ряд команд миграции баз данных, доступ к которым можно получить во Flask-Script. На 12 строке вывод этих инструкций осуществляется с использованием аргумента db, который используется в командной строке. Чтобы просмотреть команды, которые были созданные, необходимо в терминале ввести следующее. 

(env) gvido@vm:~/flask_app$ python main2.py

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

Здесь можно увидеть, что команда db применяется для осуществления миграции баз данных. А для получения полного перечня подкоманд, необходимо ввести: 

(env) gvido@vm:~/flask_app$ python main2.py db -?

Perform database migrations




positional arguments:

  {init,revision,migrate,edit,merge,upgrade,downgrade,show,history,heads,branche 

s,current,stamp}

    init Creates a new migration repository

    revision Create a new revision file.

    migrate Alias for 'revision --autogenerate'

    edit Edit current revision.

    merge Merge two revisions together. Creates a new migration

file

    upgrade Upgrade to a later version

    downgrade Revert to a previous version

    show Show the revision denoted by the given symbol.

    history List changeset scripts in chronological order.

    heads Show current available heads in the script directory

    branches Show current branch points

    current Display the current revision for each database.

    stamp 'stamp' the revision table with the given revision;

don't run any migrations




optional arguments:

  -?, --help show this help message and exit

С помощью этих команд можно осуществлять миграцию базы данных.

Перед тем, как Alembic начнет мониторинг изменений, необходимо инсталлировать специальный репозиторий, отвечающий за миграцию. Под ним подразумевается папка, в которой хранится конфигурация Alembic и скрипты миграции. Чтобы создать ее, необходимо выполнить инструкцию init

(env) gvido@vm:~/flask_app$ python main2.py db init

(env) gvido@vm:~/flask_app$

С помощью этой команды создается папка «migrations» внутри flas_app.

Давайте приведем описание каждого из каталогов и файлов:

  • alembic.ini. Это файл конфигурации Alembic.
  • env.py. Это файл Python, открывающийся при работе с Alembic. Он связывается с базой данных, выполняет транзакцию и запускает миграцию.
  • README. Это файл README.
  • script.py.mako. Для генерации скриптов миграции используется шаблон Mako, и этот файл его содержит. 
  • version. Здесь хранятся скрипты миграции.

Как создать скрипт миграции?

Миграции баз данных находятся в скриптах миграции, которые являются того же типа, что и стандартные файлы Python. Ими определяются две функции upgrade(), downgrade(). Первая используется для того, чтобы внести изменения в базу данных, а вторая – для возвращения ее прежнего состояния. То есть, первая используется для применения миграции, а при возврате обратно – вторая.

Создание миграций возможно двумя способами:

  1. Использовать инструкцию revision для ручной миграции.
  2. Применение команды migrate для автоматической.

Ручная миграция

В этом случае в скрипте миграции функции upgrade и downgrade не содержат никаких аргументов. Инструкции Alembic дают возможность их заполнить. После этого и будут применяться изменения к базе данных. 

Этот вид миграции полезен тогда, когда требуется полный доступ к процессу миграции. 

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

(env) gvido@vm:~/flask_app$ python main2.py db revision -m  "Initial migration"

Таким образом мы создаем новый скрипт миграции в папке migrations/version. Название файла должно быть такого вида: 

someid_initial_migration.py. 

"""Initial migration




Revision ID: 945fc7313080

Revises:

Create Date: 2019-06-03 14:39:27.854291




"""

from alembic import op

import sqlalchemy as sa





# идентификаторы изменений, используемые Alembic.

revision = '945fc7313080'

down_revision = None

branch_labels = None

depends_on = None





def upgrade():

    pass

    




def downgrade():

    pass

Это типичное содержимое файла. В нем всегда начало – это комментарии. В нем указывается сообщение, заданное с использованием метки -m, ID изменения и время его создания. 

Далее указываются идентификаторы модификаций. Каждый создаваемый скрипт имеет уникальный идентификатор, хранимый в переменной revision. На следующей строке есть переменная down_revision со значением None. Она нужна для того, чтобы определять конкретную миграцию, которая выполняется, а также очередность запуска.

Теперь давайте внесем изменения в файл миграции, чтобы добавить операции создания и удаления таблицы для функций upgrade() и downgrade().

Теперь наша задача – внести изменения в файл миграции, чтобы появилась возможность добавить операции создания и удаления таблицы для функций upgrade() и downgrade() соответственно.

Что касается первой функции, то здесь применяется инструкция create_table(), а во второй – drop_table(). Они задействуют одноименные операторы.

Когда миграция запускается в первый раз, создается таблица users. Если же происходит откат, то она удаляется с помощью этой же миграции. 

Автоматическая миграция

Перед тем, как двигаться дальше, необходимо убедиться в том, что вы начинаете с чистого листа. То есть, все миграции, которые созданы в прошлом разделе, удалены.

Автоматическая миграция создает код для функция upgrade() и downgrade() после сравнения моделей с текущей версией базы данных. Чтобы создать автоматическую миграцию, необходимо воспользоваться специальной командой migrate, которая фактически выполняет те же действия, что и revision –-autogenerate.

Итак, вводим команду migrate в терминале.

Далее открываем наш main2.py, чтобы добавить модель Employee после модели Feedback

#...

class Employee(db.Model):

    __tablename__ = 'employees'

    id = db.Column(db.Integer(), primary_key=True)

    name = db.Column(db.String(255), nullable=False)

    designation = db.Column(db.String(255), nullable=False)

    doj = db.Column(db.Date(), nullable=False)

#...

Затем необходимо еще раз выполнить команду db migrate. На этот раз Alembic определяет, что добавлена таблица, и создает специальный скрипт для миграции функций. 

(env) gvido@vm:~/flask_app$ python main2.py db migrate -m  "Adding employees table"

А окончательный вид скрипта миграции будет следующим. 

"""Adding employees table




Revision ID: 6e059688f04e

Revises:

Create Date: 2019-06-03 16:01:28.030320




"""

from alembic import op

import sqlalchemy as sa





# идентификаторы изменений, используемые Alembic.

revision = '6e059688f04e'

down_revision = None

branch_labels = None

depends_on  = None





def upgrade():

    # ### автоматически генерируемые команды Alembic - пожалуйста, настройте! ###

    op.create_table('employees',

    sa.Column('id', sa.Integer(), nullable=False),

    sa.Column('name', sa.String(length=255), nullable=False),

    sa.Column('designation', sa.String(length=255),  nullable=False),

    sa.Column('doj', sa.Date(), nullable=False),

    sa.PrimaryKeyConstraint('id')

)

    # ### конец команд Alembic ###





def downgrade():

    # ### автоматически генерируемые команды Alembic - пожалуйста, настройте! ###

    op.drop_table('employees')

    # ### конец команд Alembic ###

Заключение

Таким образом, миграция баз данных во Flask – это довольно простая процедура, которая может быть как ручной, так и автоматической. Каждый из этих процессов включает множество аспектов и нюансов, которые следует рассматривать отдельно. Но это уже мы сделаем в других материалах.

ОфисГуру
Adblock
detector