a template tag to invoke a method on an object with a variable

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
##############################################################################
#
@register.tag(name = 'method_arg')
def method_arg(parser, token):
    """
    This tag allows us to call the given method with the given
    argument and set the resultant value to a variable in our context.
    ie: {% method_arg foo bar user as post %} would result in the
    variable 'post' getting the result of evaluating foo.bar(user).
    If the argument is surrounded by quotes, then it is considered a
    string and not a variable to be resolved.
    """
    try:
        tag_name, var, method_name, arg, ign, dst = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError, "%r requires arguments in the " \
              "format of <variable> <methodname> <argument> as <variable>."
    if ign.lower() != "as":
        raise template.TemplateSyntaxError, "%r requires arguments in the " \
              "format of <variable> <methodname> <argument> as <variable>."
    return MethodArgNode(var, method_name, arg, dst)

class MethodArgNode(template.Node):
    """
    The template node sub-class that does the work of looking up the
    method you wish to invoke in your template, resolving the variable
    to pass to it and setting the resultant value in the template's
    context.
    """
    def __init__(self, var, method_name, arg, dst):
        self.var = var
        self.method_name = method_name
        self.arg = arg
        self.dest = dst

    def render(self, context):
        try:
            obj = resolve_variable(self.var, context)
            if hasattr(obj, self.method_name) and \
               isinstance(getattr(obj, self.method_name), MethodType):
                if self.arg[0] == self.arg[-1] and self.arg[0] in ('"', "'"):
                    context[self.dest] = \
                                getattr(obj, self.method_name)(self.arg[1:-1])
                else:
                    context[self.dest] = getattr(obj, self.method_name)\
                                         (resolve_variable(self.arg, context))
        except:
            # render() should never raise any exception. If something goes
            # wrong we need to log it somewhere else, not chuck it up the
            # call stack.
            #
            raise
            pass
        return ""

More like this

  1. fancy_if by Scanner 6 years, 1 month ago
  2. Per-Instance On-Model M2M Caching by bryanhelmig 2 years, 10 months ago
  3. Complex Formsets, Redux by smagala 3 years, 2 months ago
  4. Functional Filters by waterson 5 years, 7 months ago
  5. Parse TemplateTag Variables Safely by evan_schulz 4 years, 10 months ago

Comments

(Forgotten your password?)