123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108 |
- import jinja2
-
- from django.conf import settings
- from django.template import TemplateDoesNotExist, TemplateSyntaxError
- from django.utils.functional import cached_property
- from django.utils.module_loading import import_string
-
- from .base import BaseEngine
-
-
- class Jinja2(BaseEngine):
-
- app_dirname = 'jinja2'
-
- def __init__(self, params):
- params = params.copy()
- options = params.pop('OPTIONS').copy()
- super().__init__(params)
-
- self.context_processors = options.pop('context_processors', [])
-
- environment = options.pop('environment', 'jinja2.Environment')
- environment_cls = import_string(environment)
-
- if 'loader' not in options:
- options['loader'] = jinja2.FileSystemLoader(self.template_dirs)
- options.setdefault('autoescape', True)
- options.setdefault('auto_reload', settings.DEBUG)
- options.setdefault('undefined',
- jinja2.DebugUndefined if settings.DEBUG else jinja2.Undefined)
-
- self.env = environment_cls(**options)
-
- def from_string(self, template_code):
- return Template(self.env.from_string(template_code), self)
-
- def get_template(self, template_name):
- try:
- return Template(self.env.get_template(template_name), self)
- except jinja2.TemplateNotFound as exc:
- raise TemplateDoesNotExist(exc.name, backend=self) from exc
- except jinja2.TemplateSyntaxError as exc:
- new = TemplateSyntaxError(exc.args)
- new.template_debug = get_exception_info(exc)
- raise new from exc
-
- @cached_property
- def template_context_processors(self):
- return [import_string(path) for path in self.context_processors]
-
-
- class Template:
-
- def __init__(self, template, backend):
- self.template = template
- self.backend = backend
- self.origin = Origin(
- name=template.filename, template_name=template.name,
- )
-
- def render(self, context=None, request=None):
- from .utils import csrf_input_lazy, csrf_token_lazy
- if context is None:
- context = {}
- if request is not None:
- context['request'] = request
- context['csrf_input'] = csrf_input_lazy(request)
- context['csrf_token'] = csrf_token_lazy(request)
- for context_processor in self.backend.template_context_processors:
- context.update(context_processor(request))
- return self.template.render(context)
-
-
- class Origin:
- """
- A container to hold debug information as described in the template API
- documentation.
- """
- def __init__(self, name, template_name):
- self.name = name
- self.template_name = template_name
-
-
- def get_exception_info(exception):
- """
- Format exception information for display on the debug page using the
- structure described in the template API documentation.
- """
- context_lines = 10
- lineno = exception.lineno
- lines = list(enumerate(exception.source.strip().split("\n"), start=1))
- during = lines[lineno - 1][1]
- total = len(lines)
- top = max(0, lineno - context_lines - 1)
- bottom = min(total, lineno + context_lines)
-
- return {
- 'name': exception.filename,
- 'message': exception.message,
- 'source_lines': lines[top:bottom],
- 'line': lineno,
- 'before': '',
- 'during': during,
- 'after': '',
- 'total': total,
- 'top': top,
- 'bottom': bottom,
- }
|