Last active
March 24, 2021 20:10
-
-
Save iamjazzar/41e6856c3084b12d86d0249f886d0f0f to your computer and use it in GitHub Desktop.
Mako Templates for Django Projects
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
""" | |
Mako Template Backend | |
This is the implementation of Mako template backend in order to use | |
it as a Django Template Backend alternative in this project template | |
system. This backend is a class that inherits | |
django.template.backends.base.BaseEngine. It must implement | |
get_template() and optionally from_string(). | |
""" | |
import tempfile | |
from django.core.urlresolvers import reverse | |
from django.contrib.staticfiles.storage import staticfiles_storage | |
from django.template import TemplateDoesNotExist, TemplateSyntaxError | |
from django.template.backends.base import BaseEngine | |
from django.template.backends.utils import csrf_input_lazy, \ | |
csrf_token_lazy | |
from django.utils.module_loading import import_string | |
from mako.template import Template as MakoTemplate | |
from mako import exceptions as mako_exceptions | |
class MakoEngine(object): | |
""" | |
This is the engine that handles getting the template and | |
compiling the template the code. | |
""" | |
def __init__(self, **options): | |
""" | |
:param options: The template options that are passed to the | |
template lookup class. | |
""" | |
environment = options.pop( | |
'environment', 'mako.lookup.TemplateLookup') | |
# Just to get a dotted module path as an/a attribute/class | |
Environment = import_string(environment) | |
self.context_processors = options.pop('context_processors', []) | |
self.lookup = Environment(**options) | |
def get_template(self, name): | |
""" | |
Locates template source files from the local filesystem given | |
a template name. | |
:param name: The template name. | |
:return: the located template. | |
""" | |
return self.lookup.get_template(name) | |
def from_string(self, template_code): | |
""" | |
Compiles the template code and return the compiled version. | |
:param template_code: Textual template source. | |
:return: Returns a compiled Mako template. | |
""" | |
return MakoTemplate(template_code, lookup=self.lookup) | |
class MakoTemplates(BaseEngine): | |
""" | |
Mako Template Backend | |
""" | |
# Name of the subdirectory containing the templates for Mako engine | |
# inside an installed application. | |
app_dirname = 'mako' | |
def __init__(self, params): | |
""" | |
Fetches template options, initializing BaseEngine properties, | |
and assigning our Mako default settings. | |
Note that OPTIONS contains backend-specific settings. | |
:param params: This is simply the template dict you | |
define in your settings file. | |
""" | |
params = params.copy() | |
options = params.pop('OPTIONS').copy() | |
super(MakoTemplates, self).__init__(params) | |
# Approximate size of the collection used to store templates. | |
options.setdefault('collection_size', 5000) | |
options.setdefault('module_directory', tempfile.gettempdir()) | |
options.setdefault('output_encoding', 'utf-8') | |
options.setdefault('input_encoding', 'utf-8') | |
options.setdefault('encoding_errors', 'replace') | |
options.setdefault('filesystem_checks', True) | |
# A list of directory names which will be searched for a | |
# particular template URI | |
options.setdefault('directories', self.template_dirs) | |
self.engine = MakoEngine(**options) | |
def from_string(self, template_code): | |
""" | |
Trying to compile and return the compiled template code. | |
:raises: TemplateSyntaxError if there's a syntax error in | |
the template. | |
:param template_code: Textual template source. | |
:return: Returns a compiled Mako template. | |
""" | |
try: | |
return Template(self.engine.from_string(template_code)) | |
except mako_exceptions.SyntaxException as exc: | |
raise TemplateSyntaxError(exc.args) | |
def get_template(self, template_name): | |
""" | |
Trying to get a compiled template given a template name | |
:param template_name: The template name. | |
:raises: - TemplateDoesNotExist if no such template exists. | |
- TemplateSyntaxError if we couldn't compile the | |
template using Mako syntax. | |
:return: Compiled Template. | |
""" | |
try: | |
return Template(self.engine.get_template(template_name)) | |
except mako_exceptions.TemplateLookupException as exc: | |
raise TemplateDoesNotExist(exc.args) | |
except mako_exceptions.CompileException as exc: | |
raise TemplateSyntaxError(exc.args) | |
class Template(object): | |
""" | |
This is an implementation of template objects returned by our | |
backend that must conform to the following interface. Django | |
won't provide a BaseTemplate class because it would have only one | |
abstract method. | |
""" | |
def __init__(self, template): | |
self.template = template | |
def render(self, context=None, request=None): | |
""" | |
Render the template with a given context. Here we're adding | |
some context variables that are required for all templates in | |
the system like the statix url and the CSRF tokens, etc. | |
:param context: It must be a dict if provided | |
:param request: It must be a django.http.HttpRequest if provided | |
:return: A rendered template | |
""" | |
if context is None: | |
context = {} | |
if request is not None: | |
# As Django doesn't have a global request object, | |
# it's useful to put it in the context. | |
context['request'] = request | |
# Passing the CSRF token is mandatory. | |
context['csrf_input'] = csrf_input_lazy(request) | |
context['csrf_token'] = csrf_token_lazy(request) | |
context['static'] = staticfiles_storage.url | |
context['url'] = reverse | |
return self.template.render(**context) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
mako==1.0.6 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# ... | |
TEMPLATES = [ | |
{ | |
'BACKEND': 'backends.mako.MakoTemplates', | |
'NAME': 'mako', | |
'DIRS': [os.path.join(BASE_DIR, 'templates'),], | |
}, | |
{ | |
'BACKEND': 'django.template.backends.django.DjangoTemplates', | |
'NAME': 'django', | |
'DIRS': [os.path.join(BASE_DIR, 'templates'),], | |
'APP_DIRS': True, | |
'OPTIONS': { | |
'context_processors': [ | |
'django.template.context_processors.debug', | |
'django.template.context_processors.request', | |
'django.contrib.auth.context_processors.auth', | |
'django.contrib.messages.context_processors.messages', | |
], | |
}, | |
}, | |
] | |
# ... |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment