mirror of
https://github.com/django/django.git
synced 2025-03-25 16:50:45 +00:00
Fixed #31750 -- Made models.Field equality compare models for inherited fields.
This commit is contained in:
parent
453967477e
commit
502e75f9ed
@ -516,17 +516,37 @@ class Field(RegisterLookupMixin):
|
|||||||
def __eq__(self, other):
|
def __eq__(self, other):
|
||||||
# Needed for @total_ordering
|
# Needed for @total_ordering
|
||||||
if isinstance(other, Field):
|
if isinstance(other, Field):
|
||||||
return self.creation_counter == other.creation_counter
|
return (
|
||||||
|
self.creation_counter == other.creation_counter and
|
||||||
|
getattr(self, 'model', None) == getattr(other, 'model', None)
|
||||||
|
)
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
def __lt__(self, other):
|
def __lt__(self, other):
|
||||||
# This is needed because bisect does not take a comparison function.
|
# This is needed because bisect does not take a comparison function.
|
||||||
|
# Order by creation_counter first for backward compatibility.
|
||||||
if isinstance(other, Field):
|
if isinstance(other, Field):
|
||||||
return self.creation_counter < other.creation_counter
|
if (
|
||||||
|
self.creation_counter != other.creation_counter or
|
||||||
|
not hasattr(self, 'model') and not hasattr(other, 'model')
|
||||||
|
):
|
||||||
|
return self.creation_counter < other.creation_counter
|
||||||
|
elif hasattr(self, 'model') != hasattr(other, 'model'):
|
||||||
|
return not hasattr(self, 'model') # Order no-model fields first
|
||||||
|
else:
|
||||||
|
# creation_counter's are equal, compare only models.
|
||||||
|
return (
|
||||||
|
(self.model._meta.app_label, self.model._meta.model_name) <
|
||||||
|
(other.model._meta.app_label, other.model._meta.model_name)
|
||||||
|
)
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
def __hash__(self):
|
def __hash__(self):
|
||||||
return hash(self.creation_counter)
|
return hash((
|
||||||
|
self.creation_counter,
|
||||||
|
self.model._meta.app_label if hasattr(self, 'model') else None,
|
||||||
|
self.model._meta.model_name if hasattr(self, 'model') else None,
|
||||||
|
))
|
||||||
|
|
||||||
def __deepcopy__(self, memodict):
|
def __deepcopy__(self, memodict):
|
||||||
# We don't have to deepcopy very much here, since most things are not
|
# We don't have to deepcopy very much here, since most things are not
|
||||||
|
@ -494,6 +494,10 @@ Miscellaneous
|
|||||||
instead of :exc:`~django.core.exceptions.SuspiciousOperation` when a session
|
instead of :exc:`~django.core.exceptions.SuspiciousOperation` when a session
|
||||||
is destroyed in a concurrent request.
|
is destroyed in a concurrent request.
|
||||||
|
|
||||||
|
* The :class:`django.db.models.Field` equality operator now correctly
|
||||||
|
distinguishes inherited field instances across models. Additionally, the
|
||||||
|
ordering of such fields is now defined.
|
||||||
|
|
||||||
.. _deprecated-features-3.2:
|
.. _deprecated-features-3.2:
|
||||||
|
|
||||||
Features deprecated in 3.2
|
Features deprecated in 3.2
|
||||||
|
@ -102,6 +102,36 @@ class BasicFieldTests(SimpleTestCase):
|
|||||||
name, path, args, kwargs = Nested.Field().deconstruct()
|
name, path, args, kwargs = Nested.Field().deconstruct()
|
||||||
self.assertEqual(path, 'model_fields.tests.Nested.Field')
|
self.assertEqual(path, 'model_fields.tests.Nested.Field')
|
||||||
|
|
||||||
|
def test_abstract_inherited_fields(self):
|
||||||
|
"""Field instances from abstract models are not equal."""
|
||||||
|
class AbstractModel(models.Model):
|
||||||
|
field = models.IntegerField()
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
class InheritAbstractModel1(AbstractModel):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class InheritAbstractModel2(AbstractModel):
|
||||||
|
pass
|
||||||
|
|
||||||
|
abstract_model_field = AbstractModel._meta.get_field('field')
|
||||||
|
inherit1_model_field = InheritAbstractModel1._meta.get_field('field')
|
||||||
|
inherit2_model_field = InheritAbstractModel2._meta.get_field('field')
|
||||||
|
|
||||||
|
self.assertNotEqual(abstract_model_field, inherit1_model_field)
|
||||||
|
self.assertNotEqual(abstract_model_field, inherit2_model_field)
|
||||||
|
self.assertNotEqual(inherit1_model_field, inherit2_model_field)
|
||||||
|
|
||||||
|
self.assertLess(abstract_model_field, inherit1_model_field)
|
||||||
|
self.assertLess(abstract_model_field, inherit2_model_field)
|
||||||
|
self.assertLess(inherit1_model_field, inherit2_model_field)
|
||||||
|
|
||||||
|
self.assertNotEqual(hash(abstract_model_field), hash(inherit1_model_field))
|
||||||
|
self.assertNotEqual(hash(abstract_model_field), hash(inherit2_model_field))
|
||||||
|
self.assertNotEqual(hash(inherit1_model_field), hash(inherit2_model_field))
|
||||||
|
|
||||||
|
|
||||||
class ChoicesTests(SimpleTestCase):
|
class ChoicesTests(SimpleTestCase):
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user