diff --git a/django/db/models/options.py b/django/db/models/options.py index 9b3106f67e..e63a81c2d8 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -395,9 +395,11 @@ class Options: ) return True - @property + @cached_property def verbose_name_raw(self): """Return the untranslated verbose name.""" + if isinstance(self.verbose_name, str): + return self.verbose_name with override(None): return str(self.verbose_name) diff --git a/tests/model_meta/models.py b/tests/model_meta/models.py index 6da62be2ac..bc69d61a59 100644 --- a/tests/model_meta/models.py +++ b/tests/model_meta/models.py @@ -1,6 +1,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation from django.contrib.contenttypes.models import ContentType from django.db import models +from django.utils.translation import gettext_lazy as _ class Relation(models.Model): @@ -124,6 +125,9 @@ class Person(BasePerson): # GR fields generic_relation_concrete = GenericRelation(Relation) + class Meta: + verbose_name = _("Person") + class ProxyPerson(Person): class Meta: diff --git a/tests/model_meta/tests.py b/tests/model_meta/tests.py index fe2f6e63da..7204a5e93a 100644 --- a/tests/model_meta/tests.py +++ b/tests/model_meta/tests.py @@ -222,6 +222,17 @@ class GetFieldByNameTests(OptionsBaseTests): opts.apps.models_ready = True +class VerboseNameRawTests(SimpleTestCase): + def test_string(self): + # Clear cached property. + Relation._meta.__dict__.pop("verbose_name_raw", None) + self.assertEqual(Relation._meta.verbose_name_raw, "relation") + + def test_gettext(self): + Person._meta.__dict__.pop("verbose_name_raw", None) + self.assertEqual(Person._meta.verbose_name_raw, "Person") + + class RelationTreeTests(SimpleTestCase): all_models = (Relation, AbstractPerson, BasePerson, Person, ProxyPerson, Relating)