Fixed #31124 -- Fixed setting of get_FOO_display() when overriding inherited choices.
Regression in 2d38eb0ab9
This commit is contained in:
parent
d202846ced
commit
29c126bb34
|
@ -764,7 +764,11 @@ class Field(RegisterLookupMixin):
|
||||||
if not getattr(cls, self.attname, None):
|
if not getattr(cls, self.attname, None):
|
||||||
setattr(cls, self.attname, self.descriptor_class(self))
|
setattr(cls, self.attname, self.descriptor_class(self))
|
||||||
if self.choices is not None:
|
if self.choices is not None:
|
||||||
if not hasattr(cls, 'get_%s_display' % self.name):
|
# Don't override a get_FOO_display() method defined explicitly on
|
||||||
|
# this class, but don't check methods derived from inheritance, to
|
||||||
|
# allow overriding inherited choices. For more complex inheritance
|
||||||
|
# structures users should override contribute_to_class().
|
||||||
|
if 'get_%s_display' % self.name not in cls.__dict__:
|
||||||
setattr(
|
setattr(
|
||||||
cls,
|
cls,
|
||||||
'get_%s_display' % self.name,
|
'get_%s_display' % self.name,
|
||||||
|
|
|
@ -834,6 +834,15 @@ Note that in the case of identical date values, these methods will use the
|
||||||
primary key as a tie-breaker. This guarantees that no records are skipped or
|
primary key as a tie-breaker. This guarantees that no records are skipped or
|
||||||
duplicated. That also means you cannot use those methods on unsaved objects.
|
duplicated. That also means you cannot use those methods on unsaved objects.
|
||||||
|
|
||||||
|
.. admonition:: Overriding extra instance methods
|
||||||
|
|
||||||
|
In most cases overriding or inheriting ``get_FOO_display()``,
|
||||||
|
``get_next_by_FOO()``, and ``get_previous_by_FOO()` should work as
|
||||||
|
expected. Since they are added by the metaclass however, it is not
|
||||||
|
practical to account for all possible inheritance structures. In more
|
||||||
|
complex cases you should override ``Field.contribute_to_class()`` to set
|
||||||
|
the methods you need.
|
||||||
|
|
||||||
Other attributes
|
Other attributes
|
||||||
================
|
================
|
||||||
|
|
||||||
|
|
|
@ -31,3 +31,7 @@ Bugfixes
|
||||||
:class:`~django.contrib.postgres.aggregates.ArrayAgg` and
|
:class:`~django.contrib.postgres.aggregates.ArrayAgg` and
|
||||||
:class:`~django.contrib.postgres.aggregates.StringAgg` with ``filter``
|
:class:`~django.contrib.postgres.aggregates.StringAgg` with ``filter``
|
||||||
argument when used in a ``Subquery`` (:ticket:`31097`).
|
argument when used in a ``Subquery`` (:ticket:`31097`).
|
||||||
|
|
||||||
|
* Fixed a regression in Django 2.2.7 that caused
|
||||||
|
:meth:`~django.db.models.Model.get_FOO_display` to work incorrectly when
|
||||||
|
overriding inherited choices (:ticket:`31124`).
|
||||||
|
|
|
@ -178,6 +178,19 @@ class GetFieldDisplayTests(SimpleTestCase):
|
||||||
f = FooBar(foo_bar=1)
|
f = FooBar(foo_bar=1)
|
||||||
self.assertEqual(f.get_foo_bar_display(), 'something')
|
self.assertEqual(f.get_foo_bar_display(), 'something')
|
||||||
|
|
||||||
|
def test_overriding_inherited_FIELD_display(self):
|
||||||
|
class Base(models.Model):
|
||||||
|
foo = models.CharField(max_length=254, choices=[('A', 'Base A')])
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
abstract = True
|
||||||
|
|
||||||
|
class Child(Base):
|
||||||
|
foo = models.CharField(max_length=254, choices=[('A', 'Child A'), ('B', 'Child B')])
|
||||||
|
|
||||||
|
self.assertEqual(Child(foo='A').get_foo_display(), 'Child A')
|
||||||
|
self.assertEqual(Child(foo='B').get_foo_display(), 'Child B')
|
||||||
|
|
||||||
def test_iterator_choices(self):
|
def test_iterator_choices(self):
|
||||||
"""
|
"""
|
||||||
get_choices() works with Iterators.
|
get_choices() works with Iterators.
|
||||||
|
|
Loading…
Reference in New Issue