2010-05-10 62 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()将它从会话中删除。

相关问题