2010-05-10 2 views
2

session.flush()비 영구적 인 Elixir/SQLAlchemy 개체를 만드는 방법은 무엇입니까? 때문에 데이터베이스에서 사용할 수 없습니다 있지만 일부 외부 파일, 내가 외부 파일에서 읽은 데이터를 포함하는 SQLAlchemy의 개체를 만들고 싶지만 실행하면 데이터베이스에 기록되지 않은 레거시 데이터의

내 코드는 다음과 같습니다

try: 
    return session.query(Phone).populate_existing().filter(Phone.mac == ident).one() 
except: 
    return self.createMockPhoneFromLicenseFile(ident) 

def createMockPhoneFromLicenseFile(self, ident): 
    # Some code to read necessary data from file deleted.... 
    phone = Phone() 
    phone.mac = foo 
    phone.data = bar 
    phone.state = "Read from legacy file" 
    phone.purchaseOrderPosition = self.getLegacyOrder(ident) 
    # SQLAlchemy magic doesn't seem to work here, probably because we don't insert the created 
    # phone object into the database. So we set the id fields manually. 
    phone.order_id = phone.purchaseOrderPosition.order_id 
    phone.order_position_id = phone.purchaseOrderPosition.order_position_id 
    return phone 

모든 것이 SQLAlchemy의는 다행히 성공하지 않는 데이터베이스에 생성 된 전화 개체를 (쓰려고 응용 프로그램에서 나중에 실행되는 session.flush()에 대한 것을 제외하고 잘 작동 phone.state이기 때문에 데이터 유형이 허용하는 것보다 긴 경우), 플러시를 발행하는 함수를 중단시킵니다.

SQLAlchemy에서 이러한 개체를 쓰지 못하게 할 방법이 있습니까?

업데이트

내가 (엘릭서 문서 (어쩌면 당신이 링크를 제공 할 수 있습니까?), 그것은 나에게 가치가 시도를 보였다에서

using_mapper_options(save_on_init=False) 

아무것도 발견하지 않았지만 나는 것 전체 개체 대신 단일 인스턴스가 작성되는 것을 방지하는 방법을 선호했습니다.

처음에는 문이 아무 효과가없는 것처럼 보였고 SQLAlchemy/Elixir 버전이 너무 오래되었다고 생각했지만 그 다음에 PurchaseOrderPosition 엔터티 (수정하지 않은 항목)에 대한 연결이

으로 이루어진 것으로 나타났습니다.
phone.purchaseOrderPosition = self.getLegacyOrder(ident) 

전화 개체가 다시 기록됩니다. 진술을 삭제하면 모든 것이 잘된 것 같습니다.

+0

답변을 업데이트했습니다. –

답변

3

당신은

import elixir 
elixir.options_defaults['mapper_options'] = { 'save_on_init': False } 

당신이 세션에 자동으로 추가되는 인스턴스를 Entity 인스턴스를 방지 할 필요가있다. 이상적으로는 코드에서 가능한 한 빨리 수행해야합니다. using_mapper_options(save_on_init=False)을 통해 엔티티 단위로이 작업을 수행 할 수도 있습니다. 자세한 내용은 Elixir 문서를 참조하십시오.

업데이트 :

이는 해결책이 나타내는 비약 메일 링리스트에 this post을 참조하십시오.

또한 Ants Aasma는 Elixir 관계에서 계단식 옵션을 사용하여 SQLAlchemy에서 계단식 옵션을 설정할 수 있다고 지적했습니다. 자세한 내용은 this page을 참조하십시오.

http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#backref-cascade

돌리을 당신의 역 참조에 명시 적으로 일을 추가 할 수 있도록 :

+0

내 의견에 대한 귀하의 답변에 대한 내 업데이트 섹션을 참조하십시오. – siebert

+0

개체 생성시 암시 적 Session.add를 피하는 것 외에도 관계에 계단식을 피할 필요가 있습니다. Elixir가 문서화하지 못했다면 SQLAlchemy docs의 cascade 문서를 참조하십시오. Elixir는 여전히 그것을 허용해야합니다. –

0

기본적으로 sqlalchemy는 기본적으로 그렇지 않습니다.

다음의 자체 포함 된 예제 코드를 고려하십시오.

from sqlalchemy import Column, Integer, Unicode, create_engine 
from sqlalchemy.orm import create_session 
from sqlalchemy.ext.declarative import declarative_base 

e = create_engine('sqlite://') 
Base = declarative_base(bind=e) 

class User(Base): 
    __tablename__ = 'users' 
    id = Column(Integer, primary_key=True) 
    name = Column(Unicode(50)) 

# create the empty table and a session 
Base.metadata.create_all() 
s = create_session(bind=e, autoflush=False, autocommit=False) 

# assert the table is empty 
assert s.query(User).all() == [] 

# create a new User instance but don't save it to database: 
u = User() 
u.name = 'siebert' 
# I could run s.add(u) here but I won't 

s.flush() 
s.commit() 

# assert the table is still empty 
assert s.query(User).all() == [] 

그래서 세션에 인스턴스를 추가하는 것이 무엇인지 확실하지 않습니다. 일반적으로 세션으로 이동하려면 수동으로 s.add(u)으로 전화해야합니다. 나는 엘릭서에 익숙하지 않아서 아마도 이것들은 약간의 연고가 될 것입니다 ... 어쩌면 당신은 session.expunge()을 사용하여 세션에서 그것을 제거 할 수 있습니다.

0

올드 포스트는하지만 그것이 역 참조에 계단식으로 인한했다 SQLAlchemy의 나의 경우, 유사한 문제를 건너 왔어요 세션에