由于数据库中没有遗留数据,但有些外部文件,我想创建一个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)
导致再次写入电话对象。如果我删除声明,一切似乎都没问题。
答案 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上将其关闭,以便您必须向会话明确添加内容