Skip to content

Commit

Permalink
Added support for accessing template context.
Browse files Browse the repository at this point in the history
  • Loading branch information
Ubuntu committed Jun 2, 2010
1 parent 1bc87e9 commit 74e6d39
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 4 deletions.
21 changes: 21 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,27 @@ Produces:

Oh no, it's already February 20th, 2010!

Accessing the Template Context
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Python Code::

@fancy_tag(register, takes_context)
def say_hello_to_user(context, phrase):
return u'%s, %s!' % (phrase, context['user'])

Template Context::

{'user': 'Tobias'} # Provided by a template context processor, for example

Template Code::

{% say_hello_to_user "Hallo" %}

Produces:

Hallo, Tobias!

Testing
-------

Expand Down
21 changes: 17 additions & 4 deletions fancy_tag/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,18 @@
kwarg_re = re.compile(r'([^\'"]*)=(.*)')


def fancy_tag_compiler(params, defaults, takes_var_args, takes_var_kwargs, name, node_class, parser, token):
def fancy_tag_compiler(params, defaults, takes_var_args, takes_var_kwargs, takes_context, name, node_class, parser, token):
"Returns a template.Node subclass."
bits = token.split_contents()[1:]

if takes_context:
if 'context' in params[:1]:
params = params[1:]
else:
raise TemplateSyntaxError(
"Any tag function decorated with takes_context=True "
"must have a first argument of 'context'")

# Split args and kwargs
args = []
kwargs = {}
Expand Down Expand Up @@ -56,25 +64,29 @@ def fancy_tag_compiler(params, defaults, takes_var_args, takes_var_kwargs, name,
raise TemplateSyntaxError("%s didn't get values for arguments: %s" % (
name, ', '.join(["'%s'" % p for p in unhandled_params])))

return node_class(args, kwargs, output_var)
return node_class(args, kwargs, output_var, takes_context)


def fancy_tag(library):
def fancy_tag(library, takes_context=False):
def inner(func):
params, var_args_var, var_kwargs_var, defaults = getargspec(func)

class FancyNode(Node):
def __init__(self, vars_to_resolve, kw_vars_to_resolve, output_var):
def __init__(self, vars_to_resolve, kw_vars_to_resolve, output_var, takes_context):
self.vars_to_resolve = map(Variable, vars_to_resolve)
self.kw_vars_to_resolve = dict(
[(kw, Variable(var)) for kw, var in kw_vars_to_resolve.items()])
self.output_var = output_var
self.takes_context = takes_context

def render(self, context):
args = [var.resolve(context) for var in self.vars_to_resolve]
kwargs = dict(
[(kw, var.resolve(context)) for kw, var in self.kw_vars_to_resolve.items()])

if self.takes_context:
args = [context] + args

if self.output_var is not None:
context[self.output_var] = func(*args, **kwargs)
return ''
Expand All @@ -87,6 +99,7 @@ def render(self, context):
defaults,
var_args_var is not None,
var_kwargs_var is not None,
takes_context,
getattr(func, "_decorated_function", func).__name__,
FancyNode
)
Expand Down
11 changes: 11 additions & 0 deletions tests/test_app/templatetags/example_tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,14 @@ def say_names(*args):
@fancy_tag(register)
def say_languages(**kwargs):
return ', '.join(['%s: %s' % (kw, v) for kw, v in kwargs.items()])


@fancy_tag(register, takes_context=True)
def say_hello(context, greeting):
return u'%s, %s' % (greeting, context['user'])


@fancy_tag(register, takes_context=True)
def say_hello_like_a_chump(greeting):
# Broken on purpose
return u'%s, %s' % (greeting, context['?'])
11 changes: 11 additions & 0 deletions tests/test_app/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -85,3 +85,14 @@ def testBadAsVarFails(self):
Template,
'{% load example_tags %}{% say_soup "Stone" as "bad var name" %}'
)

def testTakesContext(self):
template = Template('{% load example_tags %}{% say_hello "Hallo" %}')
self.assertEqual(template.render(Context({'user': 'Tobias'})), 'Hallo, Tobias')

def testTakesContextOnFuncThatDoesNotTakeContextFails(self):
self.assertRaises(
TemplateSyntaxError,
Template,
'{% load example_tags %}{% say_hello_like_a_chump "Hallo" %}'
)

0 comments on commit 74e6d39

Please sign in to comment.