diff --git a/django/template/context.py b/django/template/context.py index fa721a9f5f..5d66dd19fd 100644 --- a/django/template/context.py +++ b/django/template/context.py @@ -1,8 +1,9 @@ from copy import copy + +from django.conf import settings +from django.utils import lru_cache from django.utils.module_loading import import_string -# Cache of actual callables. -_standard_context_processors = None # Hard-coded processor for easier use of CSRF protection. _builtin_context_processors = ('django.core.context_processors.csrf',) @@ -170,21 +171,11 @@ class RenderContext(BaseContext): return self.dicts[-1][key] -# This is a function rather than module-level procedural code because we only -# want it to execute if somebody uses RequestContext. +@lru_cache.lru_cache() def get_standard_processors(): - from django.conf import settings - global _standard_context_processors - if _standard_context_processors is None: - processors = [] - collect = [] - collect.extend(_builtin_context_processors) - collect.extend(settings.TEMPLATE_CONTEXT_PROCESSORS) - for path in collect: - func = import_string(path) - processors.append(func) - _standard_context_processors = tuple(processors) - return _standard_context_processors + context_processors = _builtin_context_processors + context_processors += tuple(settings.TEMPLATE_CONTEXT_PROCESSORS) + return tuple(import_string(path) for path in context_processors) class RequestContext(Context): diff --git a/django/test/signals.py b/django/test/signals.py index d8c4aa93ae..b8e7193087 100644 --- a/django/test/signals.py +++ b/django/test/signals.py @@ -80,8 +80,8 @@ def update_connections_time_zone(**kwargs): @receiver(setting_changed) def clear_context_processors_cache(**kwargs): if kwargs['setting'] == 'TEMPLATE_CONTEXT_PROCESSORS': - from django.template import context - context._standard_context_processors = None + from django.template.context import get_standard_processors + get_standard_processors.cache_clear() @receiver(setting_changed) diff --git a/tests/test_client_regress/context_processors.py b/tests/test_client_regress/context_processors.py new file mode 100644 index 0000000000..8c1e413881 --- /dev/null +++ b/tests/test_client_regress/context_processors.py @@ -0,0 +1,2 @@ +def special(request): + return {'path': request.special_path} diff --git a/tests/test_client_regress/tests.py b/tests/test_client_regress/tests.py index f7dcae15cf..63e60ee8bd 100644 --- a/tests/test_client_regress/tests.py +++ b/tests/test_client_regress/tests.py @@ -9,7 +9,6 @@ import itertools from django.core.urlresolvers import reverse, NoReverseMatch from django.template import TemplateSyntaxError, Context, Template -import django.template.context from django.test import Client, TestCase, override_settings from django.test.client import encode_file, RequestFactory from django.test.utils import ContextList, str_prefix @@ -994,12 +993,11 @@ class ContextTests(TestCase): # Need to insert a context processor that assumes certain things about # the request instance. This triggers a bug caused by some ways of # copying RequestContext. - try: - django.template.context._standard_context_processors = (lambda request: {'path': request.special_path},) + with self.settings(TEMPLATE_CONTEXT_PROCESSORS=( + 'test_client_regress.context_processors.special', + )): response = self.client.get("/request_context_view/") self.assertContains(response, 'Path: /request_context_view/') - finally: - django.template.context._standard_context_processors = None def test_nested_requests(self): """