summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDiederik van der Boor <vdboor@edoburu.nl>2013-05-18 17:27:12 +0200
committerDiederik van der Boor <vdboor@edoburu.nl>2013-05-18 17:31:28 +0200
commit86e761fee88a8bf0499f6795c9a9b336d7c52873 (patch)
tree7e23a58a9bd5c9b630c9ae74e209033a01a99082
parent96cabba80805ddda9c48307cb3d75177dc94ba29 (diff)
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
-rw-r--r--django/contrib/contenttypes/models.py6
-rw-r--r--django/contrib/contenttypes/tests.py7
2 files changed, 11 insertions, 2 deletions
diff --git a/django/contrib/contenttypes/models.py b/django/contrib/contenttypes/models.py
index f0bd109b00..ce220c8487 100644
--- a/django/contrib/contenttypes/models.py
+++ b/django/contrib/contenttypes/models.py
@@ -118,11 +118,13 @@ class ContentTypeManager(models.Manager):
def _add_to_cache(self, using, ct):
"""Insert a ContentType into the cache."""
- model = ct.model_class()
- key = (model._meta.app_label, model._meta.model_name)
+ # Note it's possible for ContentType objects to be stale; model_class() will return None.
+ # 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, {})[ct.id] = ct
+
@python_2_unicode_compatible
class ContentType(models.Model):
name = models.CharField(max_length=100)
diff --git a/django/contrib/contenttypes/tests.py b/django/contrib/contenttypes/tests.py
index 7937873a00..f300294cd6 100644
--- a/django/contrib/contenttypes/tests.py
+++ b/django/contrib/contenttypes/tests.py
@@ -274,3 +274,10 @@ class ContentTypesTests(TestCase):
model = 'OldModel',
)
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())