gpt4 book ai didi

python - SQLAlchemy 双向关系关联代理

转载 作者:太空狗 更新时间:2023-10-29 21:01:26 25 4
gpt4 key购买 nike

更新:

对于遇到此问题的任何人,请使用 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"))

并将其添加到关键字:

users = association_proxy('user_keywords', 'user')

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

以下按预期工作:

>>> 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 尝试将其中一个外键列设置为空时导致完整性错误。

这样做:

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

结果:

>>> chicken.users
[None]

我错过了一些明显的东西不是吗?

最佳答案

UserKeyword 要求它同时与 KeywordUser 相关联才能持久保存。当您将它与 UserKeyword 相关联,但随后将其从 User.user_keywords 集合中删除时,它仍然与 相关联关键字

>>> 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,所以你得到那个 NULL 错误。在 INSERT 时间,该对象不被视为“孤儿”,除非它不与任何 Keyword.user_keywords User.user_keywords 相关联收藏品。只有当您说 del chicken.user_keywords[0] 或等价物时,您才会看到没有生成 INSERT 并且忘记了 UserKeyword 对象。

如果您在将对象从“rory”中删除之前将其刷新到数据库,那么事情就会发生变化。 UserKeyword 现在是永久性的,当您从“rory.keywords”中删除“chicken”时,将触发“delete-orphan”事件,确实删除了 UserKeyword,即使它仍然与 Keyword 对象相关联:

rory.keywords.append(chicken)

session.flush()

rory.keywords.remove(chicken)

session.flush()

你看到了 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}

现在一个有理智的人会问,“这不是自相矛盾吗?”此刻我会说,“绝对”。我需要查看测试用例,看看这种行为差异的基本原理是什么,我已经在代码中确定了为什么会以这种方式发生,而且我很确定这种差异是如何考虑“孤儿”的“pending”与“persistent”对象是有意为之的,但在这种特殊排列中显然会产生奇怪的结果。如果我能找到一个可行的,我可能会为此在 0.8 中进行更改。

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

关于python - SQLAlchemy 双向关系关联代理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14470688/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com