SQLAlchemy双向关系关联代理

2024-10-01 09:30:45 发布

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

更新:

对于任何有此问题的人,使用very latest SQLAlchemy这个行为已经被修复了。在

原版:

我在正确更新关联代理时遇到问题。在

使用这里的示例模型:http://docs.sqlalchemy.org/en/rel_0_7/orm/extensions/associationproxy.html#simplifying-association-objects

但是用以下行更改UserKeyword:

keyword = relationship("Keyword", backref=backref("user_keywords", cascade="all, delete-orphan"))

并将此添加到关键字:

^{pr2}$

所以关键字实例有一个用户列表。在

以下工作如预期:

>>> rory = User("rory")
>>> session.add(rory)
>>> chicken = Keyword('chicken')
>>> session.add(chicken)
>>> rory.keywords.append(chicken)
>>> chicken.users
[<__main__.User object at 0x1f1c0d0>]
>>> chicken.user_keywords
[<__main__.UserKeyword object at 0x1f1c450>]

但是搬家会做一些奇怪的事情。从关联代理列表中删除,如下所示:

>>> rory.keywords.remove(chicken)

当SA尝试将其中一个外键列设置为null时,会导致完整性错误。在

这样做:

>>> rory.user_keywords.remove(rory.user_keywords[0])

结果如下:

>>> chicken.users
[None]

我错过了一些显而易见的东西,不是吗?在


Tags: add代理列表mainsession关键字userskeyword
1条回答
网友
1楼 · 发布于 2024-10-01 09:30:45

UserKeyword要求它同时与Keyword和{}相关联才能持久化。当您将它与UserKeyword相关联,然后将其从User.user_keywords集合中移除时,它仍然与Keyword关联。在

>>> rory.keywords.remove(chicken)

# empty as we expect
>>> rory.user_keywords
[]   

# but the other side, still populated.  UserKeyword 
# has no User, but still has Keyword
>>> chicken.user_keywords
[<__main__.UserKeyword object at 0x101748d10>]

# but the User on that UserKeyword is None
>>> chicken.user_keywords[0].user is None
True

# hence accessing the "association" gives us None
# as well
>>> chicken.users
[None]

所以如果我们现在就flush()这个,你已经准备好了一个UserKeyword对象,但是它上面没有User,所以得到了空错误。在插入时,除非对象与任何Keyword.user_keywordsUser.user_keywords集合关联,否则不认为该对象是“孤立的”。只有当您说,del chicken.user_keywords[0]或等效的时候,您才会看到没有生成INSERT,并且忘记了UserKeyword对象。在

如果在将对象从“rory”中删除之前将其刷新到数据库中,那么情况会发生变化。UserKeyword现在是持久的,当您从rory.keywords公司,将触发一个“delete orphan”事件,该事件会删除UserKeyword,即使它仍然与Keyword对象关联:

^{pr2}$

您可以看到SQL:

INSERT INTO "user" (name) VALUES (%(name)s) RETURNING "user".id
{'name': 'rory'}

INSERT INTO keyword (keyword) VALUES (%(keyword)s) RETURNING keyword.id
{'keyword': 'chicken'}

INSERT INTO user_keyword (user_id, keyword_id, special_key) VALUES (%(user_id)s, %(keyword_id)s, %(special_key)s)
{'keyword_id': 1, 'special_key': None, 'user_id': 1}

DELETE FROM user_keyword WHERE user_keyword.user_id = %(user_id)s AND user_keyword.keyword_id = %(keyword_id)s
{'keyword_id': 1, 'user_id': 1}

一个通情达理的人会问:“这不是不一致吗?”现在我会说“绝对”。我需要查看测试用例,看看这种行为差异的基本原理是什么,我已经在代码中确定了为什么会以这种方式出现,而且我非常确定,对于“挂起”和“持久”对象,如何考虑“孤立”的这种差异是有意为之的,但在这种特定的排列中,显然会产生一个奇怪的结果。如果我能找到一个可行的,我可能会在0.8中对此进行更改。在

编辑:http://www.sqlalchemy.org/trac/ticket/2655总结了我将要考虑的问题。有一个专门针对这种行为的测试,需要追溯到它的起源。在

相关问题 更多 >