2013-10-12 5 views
30

첫 번째 마이그레이션에서 시드 데이터를 어떻게 삽입합니까? 마이그레이션이이 작업을위한 최선의 장소가 아니라면 가장 좋은 방법은 무엇입니까?플라스크 마이 그 레이션 또는 알렘 마이 그 레이션에서 시드 데이터 생성

"""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 ### 
+0

문서를 약간 업데이트하면 만든 테이블에서 테이블을 만들고 바로 대량으로 삽입하는 방법이 나와 있습니다. http://alembic.readthedocs.org/en/latest/ops.html#alembic.operations.Operations.create_table – iJames

+0

시드 데이터 생성과 관련하여 https://github.com/FactoryBoy/factory_boy 및 https://github.com/heavenshell/py-sqlalchemy_seed –

+0

을 참조하십시오. https://github.com/klen/mixer를 참조하십시오. –

답변

52

증류기는 동작 중 하나 bulk_insert()으로있다. 증류기 그냥 SQLAlchemy의에서 정상 execute() 기능과 같은 인 execute() 작업을, 가지고 너무

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

참고 : 문서는 (I 포함 한 일부 수정하여) 다음의 예를 제공합니다 당신이 어떤 SQL을 실행할 수 있습니다 update 문에서 사용되는 메타 데이터를 생성하는 데 사용되는 테이블이 스키마에 직접 정의

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')}) 
     ) 

공지 것을 : 문서의 예와 같이, 바랍니다. 이것은 DRY (이미 응용 프로그램에 정의 된 테이블이 아님)을 깨뜨린 것처럼 보일 수 있지만 사실 실제로 필요합니다. 응용 프로그램의 일부인 테이블 또는 모델 정의를 사용하려는 경우 응용 프로그램에서 테이블/모델을 변경하면이 마이그레이션이 중단됩니다. 마이그레이션 스크립트는 반드시 설정해야합니다. 향후 버전의 모델로 변경하여 마이그레이션 스크립트를 변경해서는 안됩니다. 응용 프로그램 모델을 사용하면 체크 아웃 한 모델의 버전에 따라 정의가 변경 될 수 있습니다 (대부분 최신 버전). 따라서 이주 스크립트에 자체 포함될 테이블 정의가 필요합니다.

또 다른 한가지는 자신의 명령으로 실행되는 스크립트에 시드 데이터를 넣어야하는지 (예 : 다른 답변에서와 같이 Flask-Script 명령 사용) 여부입니다. 이것은 사용될 수 있지만주의해야합니다. 로드하는 데이터가 테스트 데이터 인 경우 그 중 하나입니다. 그러나 "시드 데이터"는 응용 프로그램이 올바르게 작동하는 데 필요한 데이터를 의미하는 것으로 이해했습니다. 예를 들어, "역할"테이블에서 "admin"및 "user"에 대한 레코드를 설정해야하는 경우. 이 데이터는 마이그레이션의 일부로 삽입되어야한다. 스크립트는 데이터베이스의 최신 버전에서만 작동하는 반면 이주는 이주하려는 특정 버전에서 작동 함을 기 o하십시오. 스크립트가 역할 정보를로드하게하려면 "역할"테이블에 대해 다른 스키마가있는 데이터베이스의 모든 버전에 대한 스크립트가 필요할 수 있습니다.

또한 스크립트를 사용하면 마이그레이션간에 스크립트를 실행할 수 없게됩니다 (예 : 마이그레이션 3 - 4에서는 초기 마이그레이션의 시드 데이터가 데이터베이스에 있어야 함). 이제이 스크립트를 실행하기 위해 Alembic의 기본 실행 방법을 수정해야합니다. 또한이 스크립트는 시간이 지남에 따라 변경되어야한다는 점과 소스 제어에서 체크 아웃 한 응용 프로그램의 버전을 알고 있다는 사실을 여전히 무시하지 않고 있습니다.

+2

'bulk_insert()'와 반대가 있습니까? 나는 거기에 없다고 믿는다. 그것은'다운 그레이드 '를 쓰는 것을 더 어렵게 만들 것이다. 벌크 삭제 (bulk_delete)가 있었다고해도, 데이터가 애플리케이션에 의해 변경되고 '벌크 삽입 (bulk_insert)'에 의해 삽입되었을 때와 완전히 다른 것처럼 보이는 경우에는 어떻게해야합니까? 동일한 마이 그 레이션에서 테이블을 추가 한 경우에는 다운 그레이드하는 것이 안전 할 것입니다.이 경우 테이블을 삭제해야하지만 다른 경우는 쉽게 해결할 수 없습니다. 그래도 나는 당신의 답을 왜곡 할 필요가 없다고 느낍니다. – Miguel

+3

테이블이 생성 될 때 (대부분의 경우)'bulk_insert'가 완료되면, 테이블을 삭제하는 것으로 충분합니다. 그렇지 않으면'execute'를 사용하여 삭제할 수 있습니다. 이런 식으로 alembic을 사용하면 문제가되지 않지만, 이것은 데이터베이스 마이그레이션에 문제가됩니다. 그것들은 쉽지 않으며, 도구를 쉽게 만들 수있는 도구도 없습니다 (단지 더 쉽게 만들 수 있습니다). 또한, 내 의견을 추가 한 후 귀하의 답변에서 내 downvote를 제거했습니다. 아니 감정 : –

+0

@ MarkHildreth이 마이 그 레이션에서 테이블에 저장하고있어 이후 귀하의 접근 방식을 갔다 필요한 상수이며,이 테이블은 읽기 전용입니다. 임시 테이블이 매우 불안정하다는 점에 동의합니다. 감사!!! –

25

마이그레이션은, 그리고뿐만 아니라 그, 아래로 마이그레이션 위 또는 적용하면 이전에서 데이터베이스에 존재하는 데이터를 최대한 보존하는 것이 중요 스키마 변경을 제한해야합니다. 마이그레이션의 일부로 시드 데이터를 삽입하면 기존 데이터가 엉망이 될 수 있습니다.

플라스크의 대부분 기능으로 여러 가지 방법으로 구현할 수 있습니다. Flask-Script에 새로운 명령어를 추가하는 것은 좋은 방법입니다. 예를 들어 :

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

그래서 당신은 실행

python manager.py seed 
+0

왜 누군가가 투표에 실패 했습니까? –

+19

죄송 합니다만 조금은 기쁜 일이지만, "마이그레이션은 스키마 변경에만 국한되어야합니다"라고 강력하게 동의하지 않습니다. 시드 데이터를 별도의 명령으로 만들려면 대답은 좋습니다. 그러나 예를 들어, "역할"(관리자, 사용자 등)을 설치하려는 경우, 마이그레이션에 완벽하게 도움이됩니다. 실제로 이주에 넣기보다는 명령을 추가한다는 것은 이제 설치의 일부로 이주 대신 두 단계 (이주, 데이터로드)를 수행해야 함을의 L합니다. 환경에 따라 어느 쪽이든 이동하십시오. 그러나 마이그레이션이 "제한적"이어야한다고 말하지 마십시오. –

+0

Ok 위와 같이 마이그레이션 할 때 어떻게해야할까요? –

2

MarkHildreth는 alembic이이를 어떻게 처리 할 수 ​​있는지에 대한 훌륭한 설명을 제공했습니다.그러나 OP는 플라스크 마이그레이션 마이그레이션 스크립트를 수정하는 방법에 관한 것이 었습니다. 나는 사람들에게 alembic을 들여다보아야하는 시간을 절약 할 수있는 해답을 아래에 게시 할 것입니다.

경고 Miguel의 대답은 일반적인 데이터베이스 정보와 관련하여 정확합니다. 다시 말하면, 그의 충고를 따라야하고 절대적으로이 접근법을 사용하여 데이터베이스에 "정상적인"행을 채우지 않아야합니다. 이 접근 방식은 응용 프로그램이 작동하는 데 필요한 데이터베이스 행, 특히 "시드"데이터로 생각되는 데이터의 경우에 특히 유용합니다. 데이터를 시드 수정

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하기는 migrations/versions에서 이주 스크립트를 생성합니다. 이 스크립트는 최신 버전으로 가져 오기 위해 데이터베이스에서 순서대로 실행됩니다. OP에는 이러한 자동 생성 마이그레이션 스크립트 중 하나의 예가 포함되어 있습니다. 시드 데이터를 추가하려면 적절한 자동 생성 마이그레이션 파일을 수동으로 수정해야합니다. 위에 게시 한 코드는 그 예입니다.

변경된 내용

아주 조금. 새 파일에서 list_type_table이라는 변수에 list_typecreate_table에서 반환 된 테이블을 저장하고 있음을 알 수 있습니다. 그런 다음 op.bulk_insert을 사용하여 해당 테이블을 조작하여 몇 개의 예제 행을 작성합니다.