Commit c5e5c0fc authored by Adrian Holovaty's avatar Adrian Holovaty
Browse files

Fixed #625 -- Added template-tag decorators simple_tag and inclusion_tag....

Fixed #625 -- Added template-tag decorators simple_tag and inclusion_tag. Taken from new-admin. Thanks, rjwittams

git-svn-id: http://code.djangoproject.com/svn/django/trunk@1410 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent 84eb80bb
Loading
Loading
Loading
Loading
+67 −0
Original line number Diff line number Diff line
from django.core.template import Context, Node, TemplateSyntaxError, register_tag, resolve_variable
from django.core.template_loader import get_template
from django.utils.functional import curry
from inspect import getargspec

def generic_tag_compiler(params, defaults, name, node_class, parser, token):
    "Returns a template.Node subclass."
    bits = token.contents.split()[1:]
    bmax = len(params)
    def_len = defaults and len(defaults) or 0
    bmin = bmax - def_len
    if(len(bits) < bmin or len(bits) > bmax):
        if bmin == bmax:
            message = "%s takes %s arguments" % (name, bmin)
        else:
            message = "%s takes between %s and %s arguments" % (name, bmin, bmax)
        raise TemplateSyntaxError, message
    return node_class(bits)

def simple_tag(func):
    (params, xx, xxx, defaults) = getargspec(func)

    class SimpleNode(Node):
        def __init__(self, vars_to_resolve):
            self.vars_to_resolve = vars_to_resolve

        def render(self, context):
            resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve]
            return func(*resolved_vars)

    compile_func = curry(generic_tag_compiler, params, defaults, func.__name__, SimpleNode)
    compile_func.__doc__ = func.__doc__
    register_tag(func.__name__, compile_func)
    return func

def inclusion_tag(file_name, context_class=Context, takes_context=False):
    def dec(func):
        (params, xx, xxx, defaults) = getargspec(func)
        if takes_context:
            if params[0] == 'context':
                params = params[1:]
            else:
                raise TemplateSyntaxError, "Any tag function decorated with takes_context=True must have a first argument of 'context'"

        class InclusionNode(Node):
            def __init__(self, vars_to_resolve):
                self.vars_to_resolve = vars_to_resolve

            def render(self, context):
                resolved_vars = [resolve_variable(var, context) for var in self.vars_to_resolve]
                if takes_context:
                    args = [context] + resolved_vars
                else:
                    args = resolved_vars

                dict = func(*args)

                if not getattr(self, 'nodelist', False):
                    t = get_template(file_name)
                    self.nodelist = t.nodelist
                return self.nodelist.render(context_class(dict))

        compile_func = curry(generic_tag_compiler, params, defaults, func.__name__, InclusionNode)
        compile_func.__doc__ = func.__doc__
        register_tag(func.__name__, compile_func)
        return func
    return dec