backends.py 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. """
  2. Mako Template Backend
  3. This is the implementation of Mako template backend in order to use
  4. it as a Django Template Backend alternative in this project template
  5. system. This backend is a class that inherits
  6. django.template.backends.base.BaseEngine. It must implement
  7. get_template() and optionally from_string().
  8. """
  9. import tempfile
  10. from django.urls import reverse
  11. from django.contrib.staticfiles.templatetags.staticfiles import static
  12. from django.template.base import TemplateDoesNotExist, TemplateSyntaxError
  13. from django.template.backends.base import BaseEngine
  14. from django.template.backends.utils import csrf_input_lazy, \
  15. csrf_token_lazy
  16. from django.utils.module_loading import import_string
  17. from mako.template import Template as MakoTemplate
  18. from mako import exceptions as mako_exceptions
  19. class MakoEngine(object):
  20. """
  21. This is the engine that handles getting the template and
  22. compiling the template the code.
  23. """
  24. def __init__(self, **options):
  25. """
  26. :param options: The template options that are passed to the
  27. template lookup class.
  28. """
  29. environment = options.pop(
  30. 'environment', 'mako.lookup.TemplateLookup')
  31. # Just to get a dotted module path as an/a attribute/class
  32. Environment = import_string(environment)
  33. self.context_processors = options.pop('context_processors', [])
  34. self.lookup = Environment(**options)
  35. def get_template(self, name):
  36. """
  37. Locates template source files from the local filesystem given
  38. a template name.
  39. :param name: The template name.
  40. :return: the located template.
  41. """
  42. return self.lookup.get_template(name)
  43. def from_string(self, template_code):
  44. """
  45. Compiles the template code and return the compiled version.
  46. :param template_code: Textual template source.
  47. :return: Returns a compiled Mako template.
  48. """
  49. return MakoTemplate(template_code, lookup=self.lookup)
  50. class MakoBackend(BaseEngine):
  51. """
  52. Mako Template Backend
  53. """
  54. # Name of the subdirectory containing the templates for Mako engine
  55. # inside an installed application.
  56. app_dirname = 'mako'
  57. def __init__(self, parameters):
  58. """
  59. Fetches template options, initializing BaseEngine properties,
  60. and assigning our Mako default settings.
  61. Note that OPTIONS contains backend-specific settings.
  62. :param params: This is simply the template dict you
  63. define in your settings file.
  64. """
  65. params = parameters.copy()
  66. options = params.pop('OPTIONS').copy()
  67. super(MakoBackend, self).__init__(params)
  68. # Approximate size of the collection used to store templates.
  69. options.setdefault('collection_size', 5000)
  70. options.setdefault('module_directory', tempfile.gettempdir())
  71. options.setdefault('output_encoding', 'utf-8')
  72. options.setdefault('input_encoding', 'utf-8')
  73. options.setdefault('encoding_errors', 'replace')
  74. options.setdefault('filesystem_checks', True)
  75. # A list of directory names which will be searched for a
  76. # particular template URI
  77. options.setdefault('directories', self.template_dirs)
  78. self.engine = MakoEngine(**options)
  79. def from_string(self, template_code):
  80. """
  81. Trying to compile and return the compiled template code.
  82. :raises: TemplateSyntaxError if there's a syntax error in
  83. the template.
  84. :param template_code: Textual template source.
  85. :return: Returns a compiled Mako template.
  86. """
  87. try:
  88. return Template(self.engine.from_string(template_code))
  89. except mako_exceptions.SyntaxException as exc:
  90. raise TemplateSyntaxError(exc.args)
  91. def get_template(self, template_name):
  92. """
  93. Trying to get a compiled template given a template name
  94. :param template_name: The template name.
  95. :raises: - TemplateDoesNotExist if no such template exists.
  96. - TemplateSyntaxError if we couldn't compile the
  97. template using Mako syntax.
  98. :return: Compiled Template.
  99. """
  100. try:
  101. return Template(self.engine.get_template(template_name))
  102. except mako_exceptions.TemplateLookupException as exc:
  103. raise TemplateDoesNotExist(exc.args)
  104. except mako_exceptions.CompileException as exc:
  105. raise TemplateSyntaxError(exc.args)
  106. class Template(object):
  107. """
  108. This is an implementation of template objects returned by our
  109. backend that must conform to the following interface. Django
  110. won't provide a BaseTemplate class because it would have only one
  111. abstract method.
  112. """
  113. def __init__(self, template):
  114. self.template = template
  115. def render(self, context=None, request=None):
  116. """
  117. Render the template with a given context. Here we're adding
  118. some context variables that are required for all templates in
  119. the system like the statix url and the CSRF tokens, etc.
  120. :param context: It must be a dict if provided
  121. :param request: It must be a django.http.HttpRequest if provided
  122. :return: A rendered template
  123. """
  124. if context is None:
  125. context = {}
  126. if request is not None:
  127. # As Django doesn't have a global request object,
  128. # it's useful to put it in the context.
  129. context['request'] = request
  130. # Passing the CSRF token is mandatory.
  131. context['csrf_input'] = csrf_input_lazy(request)
  132. context['csrf_token'] = csrf_token_lazy(request)
  133. context['static'] = static
  134. context['url'] = reverse
  135. return self.template.render(**context)