Opened 4 hours ago

Last modified 3 hours ago

#37309 new Bug

`Model.__eq__` treats distinct unsaved composite-PK instances as equal — at Version 2

Reported by: Denny Biasiolli Owned by:
Component: Database layer (models, ORM) Version: 5.2
Severity: Normal Keywords: compositeprimarykey _is_pk_set
Cc: Triage Stage: Unreviewed
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: yes UI/UX: no

Description (last modified by Denny Biasiolli)

Model.__eq__ still uses pk is None to decide whether an instance is unsaved. That is wrong for composite primary keys (pk is a tuple) and for db_default PKs (DatabaseDefault is not None).

>>> User() == User()
True
>>> User(tenant_id=1) == User(tenant_id=1)
True

Documented contract (and simple-PK behavior since #18864 / #18250) is that unsaved instances are equal only to themselves. __hash__ already uses _is_pk_set() and raises for an unset PK.

The XML serializer has the same leftover (if obj.pk is not None) and emits pk='["None", "None"]' for an unsaved composite instance instead of omitting the attribute.

Proposed fix: use _is_pk_set() in both places, matching __hash__ and the rest of the #373 conversion.

Related: #18864, #18250, #373.

PR here: https://github.com/django/django/pull/21861

Change History (2)

comment:1 by Denny Biasiolli, 4 hours ago

Description: modified (diff)

comment:2 by Denny Biasiolli, 3 hours ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top