如何创建一个非持久的Elixir/SQLAlchemy对象?

2024-09-30 01:30:26 发布

您现在位置:Python中文网/ 问答频道 /正文

由于旧数据在数据库中不可用,但有些外部文件可用,所以我想创建一个SQLAlchemy对象,该对象包含从外部文件读取的数据,但如果执行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 

除了在应用程序稍后执行的session.flush()上,SQLAlchemy尝试将创建的Phone对象写入数据库(幸运的是,这没有成功,因为电话.状态超出数据类型允许的长度),这将中断发出刷新的函数。在

有什么方法可以阻止SQLAlchemy尝试编写这样的对象吗?在

更新

但我什么也没发现

^{pr2}$

在Elixir文档中(也许您可以提供一个链接?),在我看来,它值得一试(我更希望使用一种方法来防止编写单个实例,而不是整个实体)。在

起初,这个语句似乎没有效果,我怀疑我的SQLAlchemy/Elixir版本太旧,但是后来我发现到PurchaseOrderPosition实体(我没有修改)的连接是用

phone.purchaseOrderPosition = self.getLegacyOrder(ident) 

导致再次写入phone对象。如果我把这句话删掉,一切都会好起来的。在


Tags: 文件the数据对象selfid数据库return
3条回答

但我也遇到了一个类似的问题,在我的sqlalchemy中,它是由backref上的级联引起的:

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

在backrefs上关闭它,这样您就必须显式地向会话添加内容

你必须这么做

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。在

默认情况下,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)使其转到会话。我不熟悉长生不老药,所以也许这是一些长生不老药的诡计。。。也许您可以使用^{}将其从会话中删除。在

相关问题 更多 >

    热门问题