Opened 57 minutes ago
Last modified 54 minutes ago
#37309 new Bug
`Model.__eq__` treats distinct unsaved composite-PK instances as equal
| 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 )
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.