#37309: `Model.__eq__` treats distinct unsaved composite-PK instances as equal
-------------------------------------+-------------------------------------
Reporter: Denny Biasiolli | Type: Bug
Status: new | Component: Database
| layer (models, ORM)
Version: 5.2 | Severity: Normal
Keywords: compositeprimarykey | Triage Stage:
_is_pk_set | Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 1 | UI/UX: 0
-------------------------------------+-------------------------------------
`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.
--
Ticket URL: <
https://code.djangoproject.com/ticket/37309>
Django <
https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.