如何创建非持久性Elixir / SQLAlchemy对象?

时间:2010-05-10 16:49:01

标签: python sqlalchemy python-elixir

由于数据库中没有遗留数据,但有些外部文件,我想创建一个SQLAlchemy对象,其中包含从外部文件读取的数据,但如果我执行{{1}则不会写入数据库}

我的代码如下所示:

session.flush()

一切正常,除了在应用程序后面执行的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尝试将创建的Phone对象写入数据库(幸运的是没有成功,因为phone.state比数据类型允许的长),它打破了发出冲洗的功能。

有没有办法阻止SQLAlchemy尝试编写这样的对象?

更新

虽然我在

上找不到任何东西
session.flush()
在Elixir文档中的

(也许你可以提供一个链接?),我觉得值得一试(我宁愿用一种方法来防止单个实例被写入而不是整个实体)。

起初似乎声明没有效果,我怀疑我的SQLAlchemy / Elixir版本太旧了,但后来我发现与PurchaseOrderPosition实体的连接(我没有修改)用

using_mapper_options(save_on_init=False)

导致再次写入电话对象。如果我删除声明,一切似乎都没问题。

3 个答案:

答案 0 :(得分:3)

你需要做

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

以防止您实例化的Entity个实例自动添加到会话中。理想情况下,这应该在您的代码中尽早完成。您也可以通过using_mapper_options(save_on_init=False)逐个实体地执行此操作 - 有关详细信息,请参阅Elixir文档。

<强>更新

请参阅Elixir邮件列表上的this post,表明这是解决方案。

另外,正如Ants Aasma所指出的,您可以在Elixir关系上使用级联选项在SQLAlchemy中设置级联选项。有关详细信息,请参阅this page

答案 1 :(得分: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()将其从会话中删除。

答案 2 :(得分:0)

旧帖但我遇到了类似的问题,在我的sqlalchemy案例中,它是由背板上的级联引起的:

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

在backrefs上将其关闭,以便您必须向会话明确添加内容