1
0
mirror of https://github.com/django/django.git synced 2024-12-22 09:05:43 +00:00

Fixed #35407 -- Cached model's Options.swapped.

This commit is contained in:
Adam Johnson 2024-04-29 16:06:39 +01:00 committed by Sarah Boyce
parent ceea86baa3
commit 7abe5112f4
3 changed files with 41 additions and 2 deletions

View File

@ -5,6 +5,7 @@ from collections import defaultdict
from django.apps import apps from django.apps import apps
from django.conf import settings from django.conf import settings
from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured from django.core.exceptions import FieldDoesNotExist, ImproperlyConfigured
from django.core.signals import setting_changed
from django.db import connections from django.db import connections
from django.db.models import AutoField, Manager, OrderWrt, UniqueConstraint from django.db.models import AutoField, Manager, OrderWrt, UniqueConstraint
from django.db.models.query_utils import PathInfo from django.db.models.query_utils import PathInfo
@ -230,6 +231,9 @@ class Options:
self.db_table, connection.ops.max_name_length() self.db_table, connection.ops.max_name_length()
) )
if self.swappable:
setting_changed.connect(self.setting_changed)
def _format_names(self, objs): def _format_names(self, objs):
"""App label/class name interpolation for object names.""" """App label/class name interpolation for object names."""
names = {"app_label": self.app_label.lower(), "class": self.model_name} names = {"app_label": self.app_label.lower(), "class": self.model_name}
@ -399,7 +403,7 @@ class Options:
with override(None): with override(None):
return str(self.verbose_name) return str(self.verbose_name)
@property @cached_property
def swapped(self): def swapped(self):
""" """
Has this model been swapped out for another? If so, return the model Has this model been swapped out for another? If so, return the model
@ -427,6 +431,10 @@ class Options:
return swapped_for return swapped_for
return None return None
def setting_changed(self, *, setting, **kwargs):
if setting == self.swappable and "swapped" in self.__dict__:
del self.swapped
@cached_property @cached_property
def managers(self): def managers(self):
managers = [] managers = []

View File

@ -166,6 +166,11 @@ class Relating(models.Model):
people_hidden = models.ManyToManyField(Person, related_name="+") people_hidden = models.ManyToManyField(Person, related_name="+")
class Swappable(models.Model):
class Meta:
swappable = "MODEL_META_TESTS_SWAPPED"
# ParentListTests models # ParentListTests models
class CommonAncestor(models.Model): class CommonAncestor(models.Model):
pass pass

View File

@ -3,7 +3,7 @@ from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelatio
from django.core.exceptions import FieldDoesNotExist from django.core.exceptions import FieldDoesNotExist
from django.db.models import CharField, Field, ForeignObjectRel, ManyToManyField from django.db.models import CharField, Field, ForeignObjectRel, ManyToManyField
from django.db.models.options import EMPTY_RELATION_TREE, IMMUTABLE_WARNING from django.db.models.options import EMPTY_RELATION_TREE, IMMUTABLE_WARNING
from django.test import SimpleTestCase from django.test import SimpleTestCase, override_settings
from .models import ( from .models import (
AbstractPerson, AbstractPerson,
@ -16,6 +16,7 @@ from .models import (
Relating, Relating,
Relation, Relation,
SecondParent, SecondParent,
Swappable,
) )
from .results import TEST_RESULTS from .results import TEST_RESULTS
@ -233,6 +234,31 @@ class VerboseNameRawTests(SimpleTestCase):
self.assertEqual(Person._meta.verbose_name_raw, "Person") self.assertEqual(Person._meta.verbose_name_raw, "Person")
class SwappedTests(SimpleTestCase):
def test_plain_model_none(self):
self.assertIsNone(Relation._meta.swapped)
def test_unset(self):
self.assertIsNone(Swappable._meta.swapped)
def test_set_and_unset(self):
with override_settings(MODEL_META_TESTS_SWAPPED="model_meta.Relation"):
self.assertEqual(Swappable._meta.swapped, "model_meta.Relation")
self.assertIsNone(Swappable._meta.swapped)
def test_setting_none(self):
with override_settings(MODEL_META_TESTS_SWAPPED=None):
self.assertIsNone(Swappable._meta.swapped)
def test_setting_non_label(self):
with override_settings(MODEL_META_TESTS_SWAPPED="not-a-label"):
self.assertEqual(Swappable._meta.swapped, "not-a-label")
def test_setting_self(self):
with override_settings(MODEL_META_TESTS_SWAPPED="model_meta.swappable"):
self.assertIsNone(Swappable._meta.swapped)
class RelationTreeTests(SimpleTestCase): class RelationTreeTests(SimpleTestCase):
all_models = (Relation, AbstractPerson, BasePerson, Person, ProxyPerson, Relating) all_models = (Relation, AbstractPerson, BasePerson, Person, ProxyPerson, Relating)