Skip to content

Instantly share code, notes, and snippets.

@natevw
Created November 17, 2014 23:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save natevw/f14812604be62c073461 to your computer and use it in GitHub Desktop.
Save natevw/f14812604be62c073461 to your computer and use it in GitHub Desktop.
register.simple_assignment_tag — custom Django template tag helper where result can be output directly *or* assigned as caller chooses. See https://gist.github.com/natevw/c30cd4f0c27323e3c275 for a (commented out) example of usage.
from django import template
class Library(template.Library):
def simple_assignment_tag(self, func=None, takes_context=None, name=None):
'''
Like assignment_tag but when "as" not provided, falls back to simple_tag behavior!
NOTE: this is based on Django's assignment_tag implementation, modified as needed.
'''
# (nvw) imports necessary to match original context
from django.template.base import TemplateSyntaxError, TagHelperNode, parse_bits
from inspect import getargspec
def dec(func):
params, varargs, varkw, defaults = getargspec(func)
# (nvw) added from Django's simple_tag implementation
class SimpleNode(TagHelperNode):
def render(self, context):
resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
return func(*resolved_args, **resolved_kwargs)
class AssignmentNode(TagHelperNode):
def __init__(self, takes_context, args, kwargs, target_var):
super(AssignmentNode, self).__init__(takes_context, args, kwargs)
self.target_var = target_var
def render(self, context):
resolved_args, resolved_kwargs = self.get_resolved_arguments(context)
context[self.target_var] = func(*resolved_args, **resolved_kwargs)
return ''
function_name = (name or
getattr(func, '_decorated_function', func).__name__)
def compile_func(parser, token):
bits = token.split_contents()[1:]
# if len(bits) < 2 or bits[-2] != 'as':
# raise TemplateSyntaxError(
# "'%s' tag takes at least 2 arguments and the "
# "second last argument must be 'as'" % function_name)
# (nvw) replaced above choose between AssignmentNode or SimpleNode
if bits[-2] == 'as':
target_var = bits[-1]
bits = bits[:-2]
args, kwargs = parse_bits(parser, bits, params,
varargs, varkw, defaults, takes_context, function_name)
return AssignmentNode(takes_context, args, kwargs, target_var)
else:
args, kwargs = parse_bits(parser, bits, params,
varargs, varkw, defaults, takes_context, function_name)
return SimpleNode(takes_context, args, kwargs)
compile_func.__doc__ = func.__doc__
self.tag(function_name, compile_func)
return func
if func is None:
# @register.assignment_tag(...)
return dec
elif callable(func):
# @register.assignment_tag
return dec(func)
else:
raise TemplateSyntaxError("Invalid arguments provided to assignment_tag")
@mfitzp
Copy link

mfitzp commented Aug 28, 2015

@natevw thanks for this really great. Would like to use this in a BSD-licensed project (Wooey) is that acceptable?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment