2012-08-15 7 views
20

일부 데이터베이스 데이터를 alembic 업그레이드의 일부로 수정하고 싶습니다.alembic 업그레이드의 일부로 데이터 수정

은 난 그냥 내 마이그레이션의 업그레이드에 코드를 추가 할 수 있다고 생각하지만, 다음은 실패

sqlalchemy.exc.UnboundExecutionError: Could not locate a bind configured on mapper Mapper|SmsDelivery|smsdelivery, SQL expression or this Session 

난 정말이 오류를 이해하고 있지 않다 : 다음과 같은 오류와

def upgrade(): 
    ### commands auto generated by Alembic - please adjust! ### 
    op.add_column('smsdelivery', sa.Column('sms_message_part_id', sa.Integer(), sa.ForeignKey('smsmessagepart.id'), nullable=True)) 
    ### end Alembic commands ### 

    from volunteer.models import DBSession, SmsDelivery, SmsMessagePart 

    for sms_delivery in DBSession.query(SmsDelivery).all(): 
     message_part = DBSession.query(SmsMessagePart).filter(SmsMessagePart.message_id == sms_delivery.message_id).first() 
     if message_part is not None: 
      sms_delivery.sms_message_part = message_part 

. 이 문제를 어떻게 해결할 수 있습니까? 아니면 이와 같은 작업을 가능성이 없습니까?

+1

해결 방법을 게시 할 수 있습니까? – Devi

답변

15

당신이 제공하는 코드를 발췌하여에서 달성하기 위해 노력하고 정확히 이해하기가 어렵습니다. 그러나 나는 추측하려고 노력할 것이다. 그래서 다음의 답은 제 추측에 근거 할 것입니다.

4 행 - 모듈에서 물건 (DBSession, SmsDelivery, SmsMessagePart)을 가져 오면 응용 프로그램 에서처럼이 개체로 작업하려고합니다.

오류가 SmsDelivery는 매퍼 개체임을 보여줍니다 - 그래서 약간의 표를 가리키고 있습니다. mapper 오브젝트는 유효한 sqlalchemy 연결에 바인드해야합니다. 당신은 DB 객체의 초기화 (연결 및 개체를 매핑 프로그램이 연결을 바인딩)는 일반적으로 응용 프로그램 코드에서처럼를 생략 하더군요

.

DBSession은 SQLAlchemy의 세션 객체처럼 보이는 - 너무 연결 바인딩이 있어야합니다.

증류기가 이미 연결이 준비가 열려있다 -. 당신이 영업 이익 요청하는 스키마를 dB로 변경하기위한 * 방법.

이렇게 연결해야합니다. , 연결된 데이터베이스 전체의 상호 작용을 위해
컨텍스트에서 사용할 수있는 "바인드"를 사용 : 증류기 수동 op.get_bind에 따르면

()는 현재 연결 바인드를 반환합니다

from alembic import op 
connection = op.get_bind() 

그래서 당신이 사용할 수 있습니다 쿼리를 db로 실행하는이 연결.

추신. 나는 당신이 당신의 테이블에있는 데이터에 약간의 수정을 수행하기를 원한다고 가정 할 것이다. 이 수정을 하나의 업데이트 쿼리로 공식화하려고 할 수 있습니다. Alembic은 이러한 변경을 실행하는 특별한 방법을 가지고 있습니다. 따라서 연결을 다룰 필요가 없습니다. alembic.operations.Operations.execute

execute(sql, execution_options=None) 


현재 이전 컨텍스트를 사용하여 특정 SQL을 실행한다.

SQL 스크립트 컨텍스트에서 문은 출력 스트림으로 직접 내보내집니다. 그러나이 함수는 "오프라인"모드에서 실행할 수있는 변경 스크립트를 생성하기 때문에 반환 결과는 없습니다.

매개 변수 : SQL - 모든 법적 SQLAlchemy의 표현을 포함 :

  • 문자열 sqlalchemy.sql.expression.text() 구성.
  • a sqlalchemy.sql.expression.insert() 구조체.
  • sqlalchemy.sql.expression.update()
  • sqlalchemy.sql.expression.insert() 또는
  • sqlalchemy.sql.expression.delete() 구성. SQL 표현식 언어 자습서에 설명 된대로 "실행 가능"인 거의 모든 항목이 입니다.
+0

기존 데이터를 업그레이드하는 방법을 찾고 있습니다. 귀하의 대답은 받아 들여진 대답이어야합니다. 감사! – swdev

0

는 또한 자료를 가져 오려면 다음

Base.metatada.bind = op.get_bind() 

이 후 오류없이 항상 같은 모델을 사용할 수 있어야합니다.

12

그것과 같이,이 작업을 수행 할 경우, 당신은 아마 내부의 마이그레이션을 당신의 ORM 모델 의 사본을 고정 할 것을 주목할 필요가 :

class MyType(Base): 
    __tablename__ = 'existing_table' 
    __table_args__ = {'extend_existing': True} 
    id = Column(Integer, ...) 
    .. 

def upgrade(): 
    Base.metadata.bind = op.get_bind() 

    for item in Session.query(MyType).all(): 
    ... 

그렇지 않으면 당신은 필연적 상황에서 끝날 것이다 여기서 orm 모델 변경 및 이전 마이그레이션 은 더 이상 작동하지 않습니다..

유형이 특정 지점에서 벗어날 수 있고 다시 한번 마이그레이션이 실패하므로 기본 유형 자체 (app.models.MyType)가 아니라 Base를 확장해야한다는 점에 특히주의하십시오.

관련 문제