如何创建非持久 Elixir/SQLAlchemy 对象?
由于遗留数据在数据库中不可用,但在某些外部文件中不可用,我想创建一个 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 对象写入数据库(幸运的是,这并没有不会成功,因为phone.state比数据类型允许的长度要长),这会破坏发出刷新的函数。
有什么方法可以阻止 SQLAlchemy 尝试写入这样的对象吗?
更新
虽然我在 Elixir 文档中没有找到任何内容
using_mapper_options(save_on_init=False)
(也许你可以提供一个链接?),但在我看来值得一试(我更喜欢一种方法来防止单个实例被写入而不是整个实体)。
起初,该语句似乎没有效果,我怀疑我的 SQLAlchemy/Elixir 版本太旧,但后来我发现与 PurchaseOrderPosition 实体(我没有修改)的连接导致
phone.purchaseOrderPosition = self.getLegacyOrder(ident)
电话对象重新写一下。如果我删除该声明,一切似乎都很好。
Because of legacy data which is not available in the database but some external files, I want to create a SQLAlchemy object which contains data read from the external files, but isn't written to the database if I execute session.flush()
My code looks like this:
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
Everything works fine except that on a session.flush()
executed later in the application SQLAlchemy tries to write the created Phone object to the database (which fortunately doesn't succeed, because phone.state is longer than the data type allows), which breaks the function which issues the flush.
Is there any way to prevent SQLAlchemy from trying to write such an object?
Update
While I didn't find anything on
using_mapper_options(save_on_init=False)
in the Elixir documentation (maybe you can provide a link?), it seemed to me worth a try (I would have preferred a way to prevent a single instance from being written instead of the whole entity).
At first it seemed that the statement has no effect and I suspected my SQLAlchemy/Elixir versions to be too old, but then I found out that the connection to the PurchaseOrderPosition entity (which I didn't modify) made with
phone.purchaseOrderPosition = self.getLegacyOrder(ident)
causes the phone object to be written again. If I remove the statement, everything seems to be fine.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您需要采取
措施防止您实例化的 Entity 实例自动添加到会话中。理想情况下,这应该尽早在代码中完成。您还可以通过
using_mapper_options(save_on_init=False)
在每个实体的基础上执行此操作 - 有关更多详细信息,请参阅 Elixir 文档。更新:
请参阅Elixir 邮件列表上的这篇文章表明这就是解决方案。
此外,正如 Ants Aasma 指出的那样,您可以在 Elixir 关系上使用级联选项来在 SQLAlchemy 中设置级联选项。有关更多详细信息,请参阅此页面。
You need to do
to prevent
Entity
instances which you instantiate being auto-added to the session. Ideally, this should be done as early as possible in your code. You can also do this on a per-entity basis, viausing_mapper_options(save_on_init=False)
- see the Elixir documentation for more details.Update:
See this post on the Elixir mailing list indicating that this is the solution.
Also, as Ants Aasma points out, you can use cascade options on the Elixir relationship to set up cascade options in SQLAlchemy. See this page for more details.
嗯,默认情况下 sqlalchemy 不会。
考虑以下独立的示例代码。
所以我不确定将您的实例隐式添加到会话中的原因是什么。通常你必须手动调用 s.add(u) 才能使其进入会话。我对 elixir 不熟悉,所以也许这是一些 elixir 诡计...也许你可以使用
session.expunge()
。Well, sqlalchemy doesn't, by default.
Consider the following self-contained example code.
So I'm not sure what's implicity adding your instances to the session. Normally you have to manually call
s.add(u)
to make it go to the session. I'm not familiar with elixir so perhaps this is some elixir trickery... Maybe you could remove it from the session, by usingsession.expunge()
.老帖子,但我遇到了类似的问题,就我而言,在 sqlalchemy 中,它是由反向引用级联引起的:
http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#backref-cascade
在你的 backrefs 上关闭它,这样你就必须显式地将东西添加到会议
Old post but I came across a similar issue, in my case in sqlalchemy it was caused by cascading on backrefs:
http://docs.sqlalchemy.org/en/rel_0_7/orm/session.html#backref-cascade
Turn it off on your backrefs so that you have to explicitly add things to the session