2010-05-10 44 views
2

因爲這是不可用的數據庫,但一些外部文件,我想創建一個包含數據從外部文件中讀取一個SQLAlchemy的對象,但不寫,如果我執行數據庫遺留數據的session.flush()如何創建非持久化Elixir/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

我更新了我的答案。 – 2010-05-11 21:51:22

回答

3

你需要做的

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

以防止您被實例化自動添加到會話Entity實例。理想情況下,應儘早在代碼中完成此操作。您也可以通過using_mapper_options(save_on_init=False)以每個實體爲基礎執行此操作 - 有關更多詳細信息,請參閱Elixir文檔。

更新:

this post表明這是解決方案的藥劑郵件列表上。另外,正如螞蟻Aasma指出的那樣,您可以使用Elixir關係上的級聯選項在SQLAlchemy中設置級聯選項。有關更多詳細信息,請參閱this page

+0

請參閱我的問題中的更新部分,以獲得對您的答案的評論。 – siebert 2010-05-11 14:28:21

+0

除了避免在對象創建上隱含Session.add,您還需要避免級聯關係。如果Elixir沒有記錄它,請參閱SQLAlchemy文檔中的級聯文檔,Elixir仍應允許它被設置。 – 2010-05-11 16:08:19

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()將它從會話中刪除。

相關問題