簡體   English   中英

SQLAlchemy雙向關系關聯代理

[英]SQLAlchemy Bidirectional Relationship association proxy

更新:

對於有此問題的任何人,使用最新的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嘗試將其中一個外鍵列設置為null時,會導致完整性錯誤。

這樣做:

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

結果如下:

>>> chicken.users
[None]

我錯過了一些明顯沒有的東西嗎?

UserKeyword要求它同時與KeywordUser相關聯UserKeyword 當您將其與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]

因此,如果我們現在要刷新(),你已經准備好了一個UserKeyword對象,但它上面沒有User ,所以你得到了NULL錯誤。 在INSERT時,該對象不被視為“孤兒”,除非它與任何Keyword.user_keywords User.user_keywords集合User.user_keywords 只有當您說del chicken.user_keywords[0]或等效時,您才會看到沒有生成INSERT並且忘記了UserKeyword對象。

如果您要在將對象從“rory”中刪除之前將對象刷新到數據庫,那么事情會發生變化。 UserKeyword現在是持久的,而當你從“rory.keywords”,“刪除孤兒”事件打完這刪除刪除“雞” 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}

現在一個理智的人會問,“這不是不一致嗎?” 而目前我會說,“絕對”。 我需要查看測試用例以了解這種行為差異的基本原理,我已經在代碼中確定了為什么它會以這種方式出現,而且我很確定這種“孤兒”如何被考慮的區別“待定”與“持久”對象是故意的,但在這種特定的排列中顯然會產生奇怪的結果。 如果我能找到一個可行的話,我可能會在0.8中做出改變。

編輯: http//www.sqlalchemy.org/trac/ticket/2655總結了我將要考慮的問題。 特別是對這種行為進行了測試,需要追溯到它的起源。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM