Source code for mezzanine.template

from __future__ import unicode_literals

from functools import wraps

from django import template
from django.template.context import Context
from django.template.loader import get_template, select_template

from mezzanine.utils.device import templates_for_device


[docs]class Library(template.Library): """ Extends ``django.template.Library`` providing several shortcuts that attempt to take the leg-work out of creating different types of template tags. """
[docs] def as_tag(self, tag_func): """ Creates a tag expecting the format: ``{% tag_name as var_name %}`` The decorated func returns the value that is given to ``var_name`` in the template. """ @wraps(tag_func) def tag_wrapper(parser, token): class AsTagNode(template.Node): def render(self, context): parts = token.split_contents() # Resolve variables if their names are given. def resolve(arg): try: return template.Variable(arg).resolve(context) except template.VariableDoesNotExist: return arg args, kwargs = [], {} for arg in parts[1:-2]: if "=" in arg: name, val = arg.split("=", 1) if name in tag_func.__code__.co_varnames: kwargs[name] = resolve(val) continue args.append(resolve(arg)) context[parts[-1]] = tag_func(*args, **kwargs) return "" return AsTagNode() return self.tag(tag_wrapper)
[docs] def render_tag(self, tag_func): """ Creates a tag using the decorated func as the render function for the template tag node. The render function takes two arguments - the template context and the tag token. """ @wraps(tag_func) def tag_wrapper(parser, token): class RenderTagNode(template.Node): def render(self, context): return tag_func(context, token) return RenderTagNode() return self.tag(tag_wrapper)
[docs] def to_end_tag(self, tag_func): """ Creates a tag that parses until it finds the corresponding end tag, eg: for a tag named ``mytag`` it will parse until ``endmytag``. The decorated func's return value is used to render the parsed content and takes three arguments - the parsed content between the start and end tags, the template context and the tag token. """ @wraps(tag_func) def tag_wrapper(parser, token): class ToEndTagNode(template.Node): def __init__(self): end_name = "end%s" % tag_func.__name__ self.nodelist = parser.parse((end_name,)) parser.delete_first_token() def render(self, context): args = (self.nodelist.render(context), context, token) return tag_func(*args[:tag_func.__code__.co_argcount]) return ToEndTagNode() return self.tag(tag_wrapper)
[docs] def inclusion_tag(self, name, context_class=Context, takes_context=False): """ Replacement for Django's ``inclusion_tag`` which looks up device specific templates at render time. """ def tag_decorator(tag_func): @wraps(tag_func) def tag_wrapper(parser, token): class InclusionTagNode(template.Node): def render(self, context): if not getattr(self, "nodelist", False): try: request = context["request"] except KeyError: t = get_template(name) else: ts = templates_for_device(request, name) t = select_template(ts) self.template = t parts = [template.Variable(part).resolve(context) for part in token.split_contents()[1:]] if takes_context: parts.insert(0, context) result = tag_func(*parts) autoescape = context.autoescape context = context_class(result, autoescape=autoescape) return self.template.render(context) return InclusionTagNode() return self.tag(tag_wrapper) return tag_decorator