Opened 3 weeks ago

Closed 3 weeks ago

#37309 closed Bug (fixed)

`Model.__eq__` treats distinct unsaved composite-PK instances as equal

Reported by: Denny Biasiolli Owned by: Denny Biasiolli
Component: Database layer (models, ORM) Version: 5.2
Severity: Normal Keywords: compositeprimarykey _is_pk_set
Cc: Triage Stage: Ready for checkin
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 (8)

comment:1 by Denny Biasiolli, 3 weeks ago

Description: modified (diff)

comment:2 by Denny Biasiolli, 3 weeks ago

Description: modified (diff)

comment:3 by Jacob Walls, 3 weeks ago

Triage Stage: UnreviewedReady for checkin

Small suggestion to move the release note and split into two commits, otherwise looks g2g.

comment:4 by Jacob Walls <jacobtylerwalls@…>, 3 weeks ago

Owner: set to Jacob Walls <jacobtylerwalls@…>
Resolution: fixed
Status: newclosed

In 8d1c673:

Fixed #37309 -- Used _is_pk_set() in Model.eq.

Composite and db_default primary keys are not None when unset, so the
old pk is None check treated distinct unsaved instances as equal.

comment:5 by Jacob Walls <jacobtylerwalls@…>, 3 weeks ago

In 6126f5d:

Refs #37309 -- Used _is_pk_set() in the XML serializer.

Unsaved composite and db_default primary keys are not None, so the old
pk is None check emitted a dummy pk attribute in XML dumps.

comment:6 by Jacob Walls, 3 weeks ago

Resolution: fixed
Status: closednew

comment:7 by Jacob Walls, 3 weeks ago

Owner: changed from Jacob Walls <jacobtylerwalls@…> to Denny Biasiolli
Status: newassigned

comment:8 by Jacob Walls, 3 weeks ago

Resolution: fixed
Status: assignedclosed
Note: See TracTickets for help on using tickets.
Back to Top