Создание данных семян в миграциях с флягой или миграции

Как я могу вставить некоторые данные семян в первую миграцию? Если миграция не лучшее место для этого, то в чем лучшая практика?

"""empty message Revision ID: 384cfaaaa0be Revises: None Create Date: 2013-10-11 16:36:34.696069 """ # revision identifiers, used by Alembic. revision = '384cfaaaa0be' down_revision = None from alembic import op import sqlalchemy as sa def upgrade(): ### commands auto generated by Alembic - please adjust! ### op.create_table('list_type', sa.Column('id', sa.Integer(), nullable=False), sa.Column('name', sa.String(length=80), nullable=False), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('name') ) op.create_table('job', sa.Column('id', sa.Integer(), nullable=False), sa.Column('list_type_id', sa.Integer(), nullable=False), sa.Column('record_count', sa.Integer(), nullable=False), sa.Column('status', sa.Integer(), nullable=False), sa.Column('sf_job_id', sa.Integer(), nullable=False), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('compressed_csv', sa.LargeBinary(), nullable=True), sa.ForeignKeyConstraint(['list_type_id'], ['list_type.id'], ), sa.PrimaryKeyConstraint('id') ) ### end Alembic commands ### # ==> INSERT SEED DATA HERE <== def downgrade(): ### commands auto generated by Alembic - please adjust! ### op.drop_table('job') op.drop_table('list_type') ### end Alembic commands ### 

3 Solutions collect form web for “Создание данных семян в миграциях с флягой или миграции”

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)}, ] ) 

Заметим также, что у alembic есть операция 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 по умолчанию для запуска этих сценариев. И это все еще не игнорирует проблемы с тем, что эти скрипты со временем должны будут меняться, и кто знает, какую версию вашего приложения вы проверили из источника управления.

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

Как и большинство вещей с Flask, вы можете реализовать это разными способами. Добавление новой команды в Flask-Script – хороший способ сделать это, на мой взгляд. Например:

 @manager.command def seed(): "Add seed data to the database." db.session.add(...) db.session.commit() 

Итак, вы запускаете:

 python manager.py seed 

MarkHildreth предоставил отличное объяснение того, как алембик может справиться с этим. Тем не менее, ОП был конкретно о том, как изменить сценарий миграции миграции флагов. Я собираюсь опубликовать ответ на этот вопрос ниже, чтобы спасти людей от времени, чтобы взглянуть на alembic вообще.

Предупреждение . Ответ Мигеля является точным в отношении обычной информации о базе данных. То есть следует следовать его совету и абсолютно не использовать этот подход для заполнения базы данных «нормальными» строками. Этот подход специально предназначен для строк базы данных, которые необходимы для работы приложения, своего рода данные, которые я считаю «семенными» данными.

Сценарий OP изменен для обработки данных:

 """empty message Revision ID: 384cfaaaa0be Revises: None Create Date: 2013-10-11 16:36:34.696069 """ # revision identifiers, used by Alembic. revision = '384cfaaaa0be' down_revision = None from alembic import op import sqlalchemy as sa def upgrade(): ### commands auto generated by Alembic - please adjust! ### list_type_table = op.create_table('list_type', sa.Column('id', sa.Integer(), nullable=False), sa.Column('name', sa.String(length=80), nullable=False), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('name') ) op.create_table('job', sa.Column('id', sa.Integer(), nullable=False), sa.Column('list_type_id', sa.Integer(), nullable=False), sa.Column('record_count', sa.Integer(), nullable=False), sa.Column('status', sa.Integer(), nullable=False), sa.Column('sf_job_id', sa.Integer(), nullable=False), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('compressed_csv', sa.LargeBinary(), nullable=True), sa.ForeignKeyConstraint(['list_type_id'], ['list_type.id'], ), sa.PrimaryKeyConstraint('id') ) ### end Alembic commands ### op.bulk_insert( list_type_table, [ {'name':'best list'}, {'name': 'bester list'} ] ) def downgrade(): ### commands auto generated by Alembic - please adjust! ### op.drop_table('job') op.drop_table('list_type') ### end Alembic commands ### 

Контекст для новых пользователей flask_migrate

Flask migrate генерирует сценарии migrations/versions при migrations/versions . Эти сценарии запускаются в порядке в базе данных, чтобы довести их до последней версии. OP включает пример одного из этих автоматически сгенерированных сценариев миграции. Чтобы добавить данные семян, необходимо вручную изменить соответствующий автоматически сгенерированный файл миграции. Код, который я опубликовал выше, является примером этого.

Что изменилось?

Очень мало. Вы заметите, что в новом файле я сохраняю таблицу, возвращенную из create_table для list_type в переменной, называемой list_type_table . Затем мы используем эту таблицу, используя op.bulk_insert чтобы создать несколько строк примеров.

  • alembic и получение последнего вставленного значения
  • sqlalchemy: выполнение raw sql с привязками параметров
  • Alembic SqlAlchemy Postgres «NameError: имя« String »не определено», пытаясь добавить поля Array (String)
  • Извлечь значения таблицы с помощью alembic и обновить другую таблицу.
  • Поддержка Alembic для нескольких схем Postgres
  • Alembic: IntegrityError: «столбец содержит пустые значения» при добавлении столбца с нулевым значением
  • Интеграция Alembic с SQLAlchemy
  • Изменение поля Enum с использованием Alembic
  • Python - лучший язык программирования в мире.