Opened 15 years ago
Closed 11 years ago
#11892 closed Bug (fixed)
Model __eq__ is not symmetric.
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Colin Copeland, anssi.kaariainen@…, marti@… | Triage Stage: | Ready for checkin |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
The Model test for equal implemented in eq is not symmetric. A non-deferred instance compares equal to a deferred instance, but a deferred instance compares unequal to a non-deferred instance. This is due to the following implementation of eq:
def __eq__(self, other): return isinstance(other, self.__class__ and self._get_pk_val() == other._get_pk_val()
This needs to be changed to:
def __eq__(self, other): return (isinstance(other, self.__class__) or isinstance(self, other.__class__)) and self._get_pk_val() == other._get_pk_val()
Which allows for complete symmetric of comparisons.
Attachments (2)
Change History (15)
by , 15 years ago
Attachment: | 11892.diff added |
---|
comment:1 by , 15 years ago
Cc: | added |
---|
comment:2 by , 15 years ago
Has patch: | set |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:3 by , 15 years ago
Patch needs improvement: | set |
---|
This patch also changes how __eq__
behaves for inherited models. Given:
class Base(models.Model): pass class Sub(Base): pass
With the patch sub.base == sub
, while currently sub.base != sub
.
It also doen't handle the case where both instances have different deferred fields: qs.defer('f1)[0] != qs.defer('f2')[0]
.
Something like the following could work, but it seems the special-casing should rather happen in deferred_class_factory
.
def __eq__(self, other): other_model = other.__class__ if getattr(other_model, '_deferred', False): other_model = other_model.mro()[1] self_model = self.__class__ if getattr(self_model, '_deferred', False): self_model = self_model.mro()[1] return issubclass(other_model, self_model) and self._get_pk_val() == other._get_pk_val()
by , 15 years ago
Attachment: | 11892.deferred_model_eq.diff added |
---|
comment:4 by , 15 years ago
Patch needs improvement: | unset |
---|
The patch uses the approach described in my previous comment.
comment:5 by , 15 years ago
Patch needs improvement: | set |
---|---|
Version: | 1.1 → SVN |
comment:6 by , 14 years ago
Severity: | → Normal |
---|---|
Type: | → Bug |
follow-up: 9 comment:8 by , 13 years ago
#16458 is about inheritance, this one is about deferred instances. They're independent issues with similar symptoms.
comment:9 by , 13 years ago
Cc: | added |
---|
comment:11 by , 12 years ago
Cc: | added |
---|
comment:12 by , 11 years ago
Patch needs improvement: | unset |
---|---|
Triage Stage: | Accepted → Ready for checkin |
Patch for #16458 is RFC.
comment:13 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Uploaded a patch with pmcnerthney's fix and an accompanying test.