2011-10-05 3 views
5

열 이름을 변경하려고합니다. 첫 번째 시도는이 스크립트를했다 :sqlalchemy-migrate를 사용하여 열 이름 마이그레이션을 변경하는 방법을 작성 하시겠습니까?

meta = MetaData() 

users = Table('users', meta, 
    Column('id', Integer, primary_key=True), 
    Column('name', String(50), unique=True), 
    Column('email', String(120), unique=True) 
    ) 

def upgrade(migrate_engine): 
    meta.bind = migrate_engine 
    users.c.id.alter(name='id') 

def downgrade(migrate_engine): 
    meta.bind = migrate_engine 
    users.c.id.alter(name='user_id') 

은 (sqlite가) 작동 내 dev에 데이터베이스에 migrate.py test 실행 등 업그레이드 및 다운 그레이드를 수행합니다. 그러나 Heroku (PostgreSQL 8.3이 사용되는)의 테스트 환경에 배포 할 때 업그레이드를 시도 할 때 추적이 발생합니다. 이 메시지는 다음과 같습니다.

sqlalchemy.exc.ProgrammingError: (ProgrammingError) column "id" does not exist 

그런 다음 업그레이드 방법으로 users.c.user_id을 사용하려고했습니다. 그것은 이미 SQLAlchemy의-마이그레이션 스크립트를 복사 - 붙여 넣기 모델에 연습을 권장

meta_old = MetaData() 
meta_new = MetaData() 

users_old = Table('users', meta_old, 
    Column('user_id', Integer, primary_key=True), 
    Column('name', String(50), unique=True), 
    Column('email', String(120), unique=True) 
    ) 

users_new = Table('users', meta_new, 
    Column('id', Integer, primary_key=True), 
    Column('name', String(50), unique=True), 
    Column('email', String(120), unique=True) 
    ) 

def upgrade(migrate_engine): 
    meta_old.bind = migrate_engine 
    users_old.c.user_id.alter(name='id') 

def downgrade(migrate_engine): 
    meta_new.bind = migrate_engine 
    users_new.c.id.alter(name='user_id') 

: 그 두 환경 :

AttributeError: user_id 

내가 지금 사용하고 해결에 실패하면이 스크립트입니다. 그러나이 여분의 중복은 나에게 너무 많은 것을 얻는다. 이것이 어떻게 이루어져야하는지 누구나 알고 있습니다. 그것이 버그라고 가정 할 때, 해결 방법을 약간 줄이는 방법에 대한 제안을 원합니다.

답변

12

내가 기대했던 것보다 훨씬 건조한 : 해결책이 있습니다. 내성! 좋아요 :

def upgrade(migrate_engine): 
    meta = MetaData(bind=migrate_engine) 
    users = Table('users', meta, autoload=True) 
    users.c.user_id.alter(name='id') 

def downgrade(migrate_engine): 
    meta = MetaData(bind=migrate_engine) 
    users = Table('users', meta, autoload=True) 
    users.c.id.alter(name='user_id') 

매력처럼 작동합니다.

+2

니스, 비록 스키마 마이그레이션에서 autoload = True를 사용하는 것을 조심스럽게 생각합니다. 미래를 향해 나가기 위해서는 다운 그레이드에서 역순으로 변경 사항을 적용하십시오! 당신이하지 않으면, 당신은 (아마도) 많은 오류가 발생합니다! –

1

메타 데이터 참조가 섞여서 SQL을 생성 할 수 없다고 생각합니다. Table 클래스에서 서로 다른 두 개의 메타 데이터 객체를 사용하고있는 것처럼 보이며 실제로 좋지 않습니다. 당신은 오직 하나만 필요합니다. 메타 데이터는 개체 업데이트, 외래 키 제약 조건 등에 대한 쿼리를 실행해야하는지 여부와 관계없이 개체의 오래된 상태를 추적하며 모든 테이블과 관계에 대해 알아야합니다.

단일 MetaData 개체를 사용하도록 변경하고 sqlalchemy.create_engine 호출에 echo=True을 전달하면 표준 출력에 사용중인 SQL 쿼리가 인쇄됩니다. Postgres와 동일한 역할 (사용자)로 로그인 한 상태에서 직접 쿼리를 실행 해보십시오. 간단한 사용 권한 문제 일 수 있습니다.

복사 복사 : 장고는 Table 및 선언적 클래스를 자체 모듈에 배치하고 가져 오는 좋은 방법이 있다고 생각합니다. 그러나 MetaData 객체를 Table 팩토리에 전달해야하므로 문제가 복잡해집니다. 싱글 톤/글로벌 메타 데이터 객체를 사용하거나 선언적으로 변환 할 수 있습니다.

한동안 나는 Table 객체를 메타 데이터로 반환하고 그 결과를 캐시하는 단일 인수 함수를 구현하기로 결정했습니다. 사실상 싱글 톤 모델 클래스를 구현합니다. 그렇다면 나는 어리석은 결정하고 선언적으로 전환했다.

+0

나는 두 개의 메타 데이터 객체를 사용하는 것이 좋습니다 아니다 알고 있습니다. 그러나 그것은 스크립트를 작동시키는 유일한 해결 방법입니다. 그것은 작동하지 않는 첫 번째 스크립트입니다. 추적에 SQL 문이 포함되어 있으며 잘못된 이름으로 열을 변경하려고합니다. 에코에 대해 잘 알고 있습니다. = 사실, 유용 할 것입니다! – PEZ

+0

복사하여 붙여 넣을 수 없습니다. 그것은 sqlalchemy-migrate USer Guide : http://packages.python.org/sqlalchemy-migrate/versioning의 조언입니다.html # writing-scripts-with-consistent-behavior sqlalchemy-migrate와 함께 선언문을 사용하는 방법을 알지 못했습니다. 가능한가? – PEZ

+0

나는 그것을 시도하지 않았다. 행운을 빕니다! – wberry

2

이것은 또한 작동합니다

from alembic import op 
.... 
def upgrade(migrate_engine): 
    op.alter_column('users', 'user_id', new_column_name='id') 

def downgrade(migrate_engine): 
    op.alter_column('users', 'id', new_column_name='user_id') 
관련 문제