Commit 37505b63 authored by Aymeric Augustin's avatar Aymeric Augustin
Browse files

Encapsulated TEMPLATE_CONTEXT_PROCESSORS in Engine.

Since RequestContext doesn't know its Engine until it's passed to
Template.render() -- and cannot without breaking a widely used public
API -- an elaborate hack is required to apply context processors.
parent 98ac69af
Loading
Loading
Loading
Loading
+30 −18
Original line number Diff line number Diff line
from copy import copy

from django.conf import settings
from django.utils import lru_cache
from django.utils.module_loading import import_string

# Hard-coded processor for easier use of CSRF protection.
_builtin_context_processors = ('django.core.context_processors.csrf',)
@@ -172,13 +169,6 @@ class RenderContext(BaseContext):
        return self.dicts[-1][key]


@lru_cache.lru_cache()
def get_standard_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):
    """
    This subclass of template.Context automatically populates itself using
@@ -190,11 +180,33 @@ class RequestContext(Context):
            use_l10n=None, use_tz=None, engine=None):
        Context.__init__(self, dict_, current_app=current_app,
                use_l10n=use_l10n, use_tz=use_tz, engine=engine)
        if processors is None:
            processors = ()
        self._request = request
        self._processors = () if processors is None else tuple(processors)
        self._processors_index = len(self.dicts)
        self.update({})         # placeholder for context processors output
        self.engine = engine    # re-run the setter in case engine is not None

    @property
    def engine(self):
        return self._engine

    @engine.setter
    def engine(self, engine):
        self._engine = engine
        if hasattr(self, '_processors_index'):
            if engine is None:
                # Unset context processors.
                self.dicts[self._processors_index] = {}
            else:
            processors = tuple(processors)
        updates = dict()
        for processor in get_standard_processors() + processors:
            updates.update(processor(request))
        self.update(updates)
                # Set context processors for this engine.
                updates = {}
                for processor in engine.template_context_processors + self._processors:
                    updates.update(processor(self._request))
                self.dicts[self._processors_index] = updates

    def new(self, values=None):
        new_context = super(RequestContext, self).new(values)
        # This is for backwards-compatibility: RequestContexts created via
        # Context.new don't include values from context processors.
        del new_context._processors_index
        return new_context
+7 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@ from django.utils.functional import cached_property
from django.utils.module_loading import import_string

from .base import Context, Lexer, Parser, Template, TemplateDoesNotExist
from .context import _builtin_context_processors


_dirs_undefined = object()
@@ -58,6 +59,12 @@ class Engine(object):
            file_charset=settings.FILE_CHARSET,
        )

    @cached_property
    def template_context_processors(self):
        context_processors = _builtin_context_processors
        context_processors += tuple(self.context_processors)
        return tuple(import_string(path) for path in context_processors)

    @cached_property
    def template_loaders(self):
        return self.get_template_loaders(self.loaders)
+0 −7
Original line number Diff line number Diff line
@@ -91,13 +91,6 @@ def reset_default_template_engine(**kwargs):
        Engine.get_default.cache_clear()


@receiver(setting_changed)
def clear_context_processors_cache(**kwargs):
    if kwargs['setting'] == 'TEMPLATE_CONTEXT_PROCESSORS':
        from django.template.context import get_standard_processors
        get_standard_processors.cache_clear()


@receiver(setting_changed)
def clear_serializers_cache(**kwargs):
    if kwargs['setting'] == 'SERIALIZATION_MODULES':