Fix NoneType error when fetching a stale ContentType with get_for_id
When a stale ContentType is fetched, the _add_to_cache() function didn't detect that `model_class()` returns `None` (which it does by design). However, the `app_label` + `model` fields can be used instead to as local cache key. Third party apps can detect stale models by checking whether `model_class()` returns `None`. Ticket: https://code.djangoproject.com/ticket/20442
This commit is contained in:
parent
96cabba808
commit
86e761fee8
|
@ -118,11 +118,13 @@ class ContentTypeManager(models.Manager):
|
||||||
|
|
||||||
def _add_to_cache(self, using, ct):
|
def _add_to_cache(self, using, ct):
|
||||||
"""Insert a ContentType into the cache."""
|
"""Insert a ContentType into the cache."""
|
||||||
model = ct.model_class()
|
# Note it's possible for ContentType objects to be stale; model_class() will return None.
|
||||||
key = (model._meta.app_label, model._meta.model_name)
|
# Hence, there is no reliance on model._meta.app_label here, just using the model fields instead.
|
||||||
|
key = (ct.app_label, ct.model)
|
||||||
self.__class__._cache.setdefault(using, {})[key] = ct
|
self.__class__._cache.setdefault(using, {})[key] = ct
|
||||||
self.__class__._cache.setdefault(using, {})[ct.id] = ct
|
self.__class__._cache.setdefault(using, {})[ct.id] = ct
|
||||||
|
|
||||||
|
|
||||||
@python_2_unicode_compatible
|
@python_2_unicode_compatible
|
||||||
class ContentType(models.Model):
|
class ContentType(models.Model):
|
||||||
name = models.CharField(max_length=100)
|
name = models.CharField(max_length=100)
|
||||||
|
|
|
@ -274,3 +274,10 @@ class ContentTypesTests(TestCase):
|
||||||
model = 'OldModel',
|
model = 'OldModel',
|
||||||
)
|
)
|
||||||
self.assertEqual(six.text_type(ct), 'Old model')
|
self.assertEqual(six.text_type(ct), 'Old model')
|
||||||
|
self.assertIsNone(ct.model_class())
|
||||||
|
|
||||||
|
# Make sure stale ContentTypes can be fetched like any other object.
|
||||||
|
# Before Django 1.6 this caused a NoneType error in the caching mechanism.
|
||||||
|
# Instead, just return the ContentType object and let the app detect stale states.
|
||||||
|
ct_fetched = ContentType.objects.get_for_id(ct.pk)
|
||||||
|
self.assertIsNone(ct_fetched.model_class())
|
||||||
|
|
Loading…
Reference in New Issue