В качестве одной из операций Alembic использует bulk_insert()
. В документации приводится следующий пример (с некоторыми исправлениями, которые я включил):
from datetime import date
from sqlalchemy.sql import table, column
from sqlalchemy import String, Integer, Date
from alembic import op
# Create an ad-hoc table to use for the insert statement.
accounts_table = table('account',
column('id', Integer),
column('name', String),
column('create_date', Date)
)
op.bulk_insert(accounts_table,
[
{'id':1, 'name':'John Smith',
'create_date':date(2010, 10, 5)},
{'id':2, 'name':'Ed Williams',
'create_date':date(2007, 5, 27)},
{'id':3, 'name':'Wendy Jones',
'create_date':date(2008, 8, 15)},
]
)
Также обратите внимание, что перегонный куб имеет операцию execute()
, которая аналогична обычная функция execute()
в SQLAlchemy: вы можете запускать любой SQL, который хотите, как показано в примере документации:
from sqlalchemy.sql import table, column
from sqlalchemy import String
from alembic import op
account = table('account',
column('name', String)
)
op.execute(
account.update().\
where(account.c.name==op.inline_literal('account 1')).\
values({'name':op.inline_literal('account 2')})
)
Обратите внимание, что таблица, которая используется для создания метаданных, используемых в операторе update
, определена непосредственно в схеме. Может показаться, что это нарушает DRY (таблица еще не определена в вашем приложении), но на самом деле это довольно необходимый. Если вы попытаетесь использовать определение таблицы или модели, которое является частью вашего приложения, вы нарушите эту миграцию, когда внесете изменения в свою таблицу / модель в своем приложении. Ваши сценарии миграции должны быть твердыми: изменение будущих версий ваших моделей не должно изменять сценарии миграции. Использование моделей приложений будет означать, что определения будут меняться в зависимости от того, какую версию моделей вы проверяли (скорее всего, последнюю). Следовательно, вам нужно, чтобы определение таблицы было автономным в сценарии миграции.
Еще одна вещь, о которой стоит поговорить, - следует ли вам помещать свои исходные данные в сценарий, который запускается как отдельная команда (например, с помощью команды Flask-Script, как показано в другом ответе). Это можно использовать, но с этим следует быть осторожным. Если данные, которые вы загружаете, являются тестовыми, это одно. Но я понял, что «исходные данные» означают данные, необходимые для правильной работы приложения. Например, если вам нужно настроить записи для «admin» и «user» в таблице «role». Эти данные ДОЛЖНЫ быть вставлены как часть миграции. Помните, что сценарий будет работать только с последней версией вашей базы данных, тогда как миграция будет работать с конкретной версией, на которую вы выполняете переход. Если вы хотите, чтобы сценарий загружал информацию о ролях, вам может понадобиться сценарий для каждой версии базы данных с другой схемой для таблицы «роли».
Кроме того, полагаясь на сценарий, вам будет сложнее запускать сценарий между миграциями (скажем, миграция 3-> 4 требует, чтобы исходные данные в начальной миграции находились в базе данных). Теперь вам нужно изменить способ запуска Alembic по умолчанию для запуска этих скриптов. И это по-прежнему не игнорирует проблемы, связанные с тем, что эти скрипты со временем должны будут меняться, и кто знает, какую версию вашего приложения вы извлекли из системы контроля версий.
person
Mark Hildreth
schedule
12.10.2013