summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--django/contrib/contenttypes/models.py20
-rw-r--r--docs/releases/1.8.10.txt3
-rw-r--r--docs/releases/1.9.3.txt3
-rw-r--r--tests/contenttypes_tests/test_models.py14
4 files changed, 30 insertions, 10 deletions
diff --git a/django/contrib/contenttypes/models.py b/django/contrib/contenttypes/models.py
index 27a5388a70..8d459f65a2 100644
--- a/django/contrib/contenttypes/models.py
+++ b/django/contrib/contenttypes/models.py
@@ -13,13 +13,15 @@ from django.utils.translation import ugettext_lazy as _
class ContentTypeManager(models.Manager):
use_in_migrations = True
- # Cache to avoid re-looking up ContentType objects all over the place.
- # This cache is shared by all the get_for_* methods.
- _cache = {}
+ def __init__(self, *args, **kwargs):
+ super(ContentTypeManager, self).__init__(*args, **kwargs)
+ # Cache shared by all the get_for_* methods to speed up
+ # ContentType retrieval.
+ self._cache = {}
def get_by_natural_key(self, app_label, model):
try:
- ct = self.__class__._cache[self.db][(app_label, model)]
+ ct = self._cache[self.db][(app_label, model)]
except KeyError:
ct = self.get(app_label=app_label, model=model)
self._add_to_cache(self.db, ct)
@@ -34,7 +36,7 @@ class ContentTypeManager(models.Manager):
def _get_from_cache(self, opts):
key = (opts.app_label, opts.model_name)
- return self.__class__._cache[self.db][key]
+ return self._cache[self.db][key]
def create(self, **kwargs):
if 'name' in kwargs:
@@ -129,7 +131,7 @@ class ContentTypeManager(models.Manager):
(though ContentTypes are obviously not created on-the-fly by get_by_id).
"""
try:
- ct = self.__class__._cache[self.db][id]
+ ct = self._cache[self.db][id]
except KeyError:
# This could raise a DoesNotExist; that's correct behavior and will
# make sure that only correct ctypes get stored in the cache dict.
@@ -144,15 +146,15 @@ class ContentTypeManager(models.Manager):
django.contrib.contenttypes.management.update_contenttypes for where
this gets called).
"""
- self.__class__._cache.clear()
+ self._cache.clear()
def _add_to_cache(self, using, ct):
"""Insert a ContentType into the cache."""
# 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
+ self._cache.setdefault(using, {})[key] = ct
+ self._cache.setdefault(using, {})[ct.id] = ct
@python_2_unicode_compatible
diff --git a/docs/releases/1.8.10.txt b/docs/releases/1.8.10.txt
index c9fbd0470d..b1319ff802 100644
--- a/docs/releases/1.8.10.txt
+++ b/docs/releases/1.8.10.txt
@@ -26,3 +26,6 @@ Bugfixes
``URLValidator`` to fix a regression in Django 1.8 (:ticket:`26204`).
* Fixed ``BoundField`` to reallow slices of subwidgets (:ticket:`26267`).
+
+* Prevented ``ContentTypeManager`` instances from sharing their cache
+ (:ticket:`26286`).
diff --git a/docs/releases/1.9.3.txt b/docs/releases/1.9.3.txt
index 625899daa0..e0447d2afe 100644
--- a/docs/releases/1.9.3.txt
+++ b/docs/releases/1.9.3.txt
@@ -49,3 +49,6 @@ Bugfixes
* Fixed a crash when passing a nonexistent template name to the cached template
loader's ``load_template()`` method (:ticket:`26280`).
+
+* Prevented ``ContentTypeManager`` instances from sharing their cache
+ (:ticket:`26286`).
diff --git a/tests/contenttypes_tests/test_models.py b/tests/contenttypes_tests/test_models.py
index eb436b6a64..75cea0a4d8 100644
--- a/tests/contenttypes_tests/test_models.py
+++ b/tests/contenttypes_tests/test_models.py
@@ -2,7 +2,7 @@ from __future__ import unicode_literals
import warnings
-from django.contrib.contenttypes.models import ContentType
+from django.contrib.contenttypes.models import ContentType, ContentTypeManager
from django.contrib.contenttypes.views import shortcut
from django.contrib.sites.shortcuts import get_current_site
from django.db.utils import IntegrityError, OperationalError, ProgrammingError
@@ -170,6 +170,18 @@ class ContentTypesTests(TestCase):
DeferredProxyModel: proxy_model_ct,
})
+ def test_cache_not_shared_between_managers(self):
+ with self.assertNumQueries(1):
+ ContentType.objects.get_for_model(ContentType)
+ with self.assertNumQueries(0):
+ ContentType.objects.get_for_model(ContentType)
+ other_manager = ContentTypeManager()
+ other_manager.model = ContentType
+ with self.assertNumQueries(1):
+ other_manager.get_for_model(ContentType)
+ with self.assertNumQueries(0):
+ other_manager.get_for_model(ContentType)
+
@override_settings(ALLOWED_HOSTS=['example.com'])
def test_shortcut_view(self):
"""