Commit 4668c142 authored by Anssi Kääriäinen's avatar Anssi Kääriäinen
Browse files

Made Model.__eq__ consider proxy models equivalent

Fixed #11892, fixed #16458, fixed #14492.
parent 40909826
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -459,7 +459,9 @@ class Model(six.with_metaclass(ModelBase)):
        return '%s object' % self.__class__.__name__

    def __eq__(self, other):
        return isinstance(other, self.__class__) and self._get_pk_val() == other._get_pk_val()
        return (isinstance(other, Model) and
                self._meta.concrete_model == other._meta.concrete_model and
                self._get_pk_val() == other._get_pk_val())

    def __ne__(self, other):
        return not self.__eq__(other)
+34 −0
Original line number Diff line number Diff line
@@ -494,6 +494,40 @@ using ``__str__()`` like this::
            # first_name and last_name will be unicode strings.
            return force_bytes('%s %s' % (self.first_name, self.last_name))

``__eq__``
----------

.. method:: Model.__eq__()

The equality method is defined such that instances with the same primary
key value and the same concrete class are considered equal. The term
concrete class means proxy model's first non-proxy parent or the class
itself if it isn't a proxy class.

For example::

    form django.db import models

    class MyModel(models.Model):
        id = models.AutoField(primary_key=True)

    class MyProxyModel(MyModel):
        class Meta:
            proxy = True

    class MultitableInherited(MyModel):
        pass

    MyModel(id=1) == MyModel(id=1)
    MyModel(id=1) == MyProxyModel(id=1)
    MyModel(id=1) != MultitableInherited(id=1)
    MyModel(id=1) != MyModel(id=2)

.. versionchanged:: 1.7

  In previous versions only instances of the exact same class and same
  primary key value were considered equal.

``get_absolute_url``
--------------------

+5 −0
Original line number Diff line number Diff line
@@ -194,6 +194,11 @@ Miscellaneous
  removes the ability for visitors to generate spurious HTTP 500 errors by
  requesting static files that don't exist or haven't been collected yet.

* The :meth:`django.db.models.Model.__eq__` method is now defined in a
  way where instances of a proxy model and its base model are considered
  equal when primary keys match. Previously only instances of exact same
  class were considered equal on primary key match.

Features deprecated in 1.7
==========================

+4 −0
Original line number Diff line number Diff line
@@ -707,6 +707,10 @@ class ModelTest(TestCase):
        with self.assertRaises(ObjectDoesNotExist):
            SelfRef.objects.get(selfref=sr)

    def test_eq(self):
        self.assertNotEqual(Article(id=1), object())
        self.assertNotEqual(object(), Article(id=1))


class ConcurrentSaveTests(TransactionTestCase):

+6 −0
Original line number Diff line number Diff line
@@ -183,3 +183,9 @@ class DeferTests(TestCase):
        with self.assertNumQueries(0):
            bc_deferred.id
        self.assertEqual(bc_deferred.pk, bc_deferred.id)

    def test_eq(self):
        s1 = Secondary.objects.create(first="x1", second="y1")
        s1_defer = Secondary.objects.only('pk').get(pk=s1.pk)
        self.assertEqual(s1, s1_defer)
        self.assertEqual(s1_defer, s1)
Loading