UserKeyword
erfordert, dass es gleichzeitig mit Keyword
und User
verbunden ist, um dauerhaft zu sein. Wenn Sie es mit einer User
und Keyword
verknüpfen, aber dann aus der User.user_keywords
Sammlung entfernen, ist es immer noch mit der Keyword
verbunden.
>>> 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]
Also, wenn wir() dieses Recht jetzt spülen sind, haben Sie ein UserKeyword
Objekt bereit bekommen zu gehen, aber es hat keine User
auf sich, so dass Sie NULL Fehler. Bei der INSERT-Zeit wird das Objekt nicht als "verwaist" betrachtet, es sei denn, es ist nicht mit einer Sammlung verbunden. Nur wenn Sie sagen würden, del chicken.user_keywords[0]
oder gleichwertig, würden Sie sehen, dass kein INSERT generiert wird und das UserKeyword
Objekt vergessen wird.
Wenn Sie das Objekt in die Datenbank leeren, bevor Sie es aus "Rory" entfernen, dann ändern sich die Dinge. Die UserKeyword
ist jetzt persistent, und wenn Sie "Huhn" aus "Rory entfernen.keywords“, ein "delete-orphan Brände" Ereignis aus der die UserKeyword
nicht löschen, obwohl es nach wie vor mit dem Keyword
Objekt zugeordnet ist:
rory.keywords.append(chicken)
session.flush()
rory.keywords.remove(chicken)
session.flush()
Sie die SQL sehen:
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}
Nun würde eine vernünftige Person fragen: "Ist das nicht inkonsequent?" Und im Moment würde ich "absolut" sagen. Ich muss in die Testfälle schauen, um zu sehen, was die Gründe für diesen Unterschied im Verhalten sind. Ich habe in dem Code festgestellt, warum es auf diese Weise auftritt, und ich bin mir ziemlich sicher, dass dieser Unterschied darin besteht, wie ein "Waisenkind" betrachtet wird "Ausstehende" gegenüber "persistenten" Objekten ist beabsichtigt, aber in dieser speziellen Permutation ergibt sich offensichtlich ein seltsames Ergebnis. Ich könnte eine Änderung in 0.8 dafür machen, wenn ich eine finden kann, die machbar ist.
bearbeiten: http://www.sqlalchemy.org/trac/ticket/2655 fasst das Problem zusammen, über das ich nachdenken muss. Es gibt einen Test speziell für dieses Verhalten, den man auf seinen Ursprung zurückverfolgen muss.
Danke Haufen zzzeek. –