Changes between Initial Version and Version 1 of Ticket #16458


Ignore:
Timestamp:
07/13/2011 10:14:24 AM (8 years ago)
Author:
Luke Plant
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • Ticket #16458

    • Property Triage Stage changed from Unreviewed to Accepted
  • Ticket #16458 – Description

    initial v1  
    1 Problem outline
    2 ---------------
     1== Problem outline ==
     2
    33In math is is a common assumption that the equality operator should be commutative, i.e. A==B would always correspond to B==A.
    44In django's Model class I found non-commutative behaviour.
    55
    66
    7 Affected code
    8 -------------
     7== Affected code ==
     8
    99file: django.db.models.base.py
    10 
     10{{{
    1111class Model(object):
    1212...
     
    1515        return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
    1616...
     17}}}
    1718
    18 
    19 Problem detail
    20 --------------
     19== Problem detail ==
    2120
    2221This implementation of __eq__() will cause a different outcome between (A==B) and (B==A) in cases where one of the two compared objects is a derived class of the other.
    2322
    2423assume this:
    25 class MyModel(models.Model)
    26 class MyDerivedModel(MyModel)
     24{{{
     25class MyModel(models.Model): pass
     26class MyDerivedModel(MyModel): pass
    2727A = MyModel()
    2828B = MyDerivedModel()
     
    3030(A==B) # --> A.__eq__ returns True if (a.pk == b.pk)
    3131(B==A) # --> B.__eq__ returns False
     32}}}
    3233
     34== Further analysis ==
    3335
    34 Further analysis
    35 ----------------
    3636I checked how derived models are created in the database (MySQL 5.0 backend). The table for MyDerivedModel does not contain its own primary key, but a reference to the PK in MyModel instead. This means that there can never be a collision between the primary key of MyModel and the primary key of MyDerivedModel.
    3737
     
    3939
    4040
    41 Suggested solution
    42 ------------------
     41== Suggested solution ==
     42
    4343Make the type comparison between self and other symmetrical.
    44 
     44{{{
    4545class Model(object):
    4646   def __eq__(self, other):
    4747        return (isinstance(other, self.__class__) or isinstance(self, other.__class__)) and \
    4848               (self._get_pk_val() == other._get_pk_val())
     49}}}
Back to Top