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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 | from django import template
from django.template.loader import get_template
from django.conf import settings
import tokenize
import StringIO
register = template.Library()
class CallNode(template.Node):
def __init__(self, template_name, *args, **kwargs):
self.template_name = template_name
self.args = args
self.kwargs = kwargs
def render(self, context):
try:
template_name = self.template_name.resolve(context)
t = get_template(template_name)
d = {}
args = d['args'] = []
kwargs = d['kwargs'] = {}
for i in self.args:
args.append(i.resolve(context))
for key, value in self.kwargs.items():
kwargs[key] = d[key] = value.resolve(context)
context.update(d)
result = t.render(context)
context.pop()
return result
except:
if settings.TEMPLATE_DEBUG:
raise
return ''
def do_call(parser, token):
"""
Loads a template and renders it with the current context.
Example::
{% call "foo/some_include" %}
{% call "foo/some_include" with arg1 arg2 ... argn %}
"""
bits = token.contents.split()
if 'with' in bits: #has 'with' key
pos = bits.index('with')
argslist = bits[pos+1:]
bits = bits[:pos]
else:
argslist = []
if len(bits) != 2:
raise template.TemplateSyntaxError, "%r tag takes one argument: the name of the template to be included" % bits[0]
path = parser.compile_filter(bits[1])
if argslist:
args = []
kwargs = {}
for i in argslist:
if '=' in i:
a, b = i.split('=', 1)
a = a.strip()
b = b.strip()
buf = StringIO.StringIO(a)
keys = list(tokenize.generate_tokens(buf.readline))
if keys[0][0] == tokenize.NAME:
kwargs[a] = parser.compile_filter(b)
else:
raise template.TemplateSyntaxError, "Argument syntax wrong: should be key=value"
else:
args.append(parser.compile_filter(i))
return CallNode(path, *args, **kwargs)
register.tag('call', do_call)
|
Comments
very use full ;) thanks
#
I had to shuffle some variable assignments around to get this to work.
Move: args = [] kwargs = {}
outside of the IF block.
#
Hi,
very good idea this call function. But it have a template error when i send parameters.
Exception Type: TemplateSyntaxError
Exception Value: Caught an exception while rendering: init() keywords must be strings
Do someone have a way to resolved it ??
Thanks
#
bits = token.contents.split() on line 46 doesn't works correctly if you pass string with whitespaces as argument (for example {% call "some.html" with "c" "d e" title="title 2" %}).
#
You can use instead: bits = token.split_contents()
#
@albrun the problem is that the keyword is a unicode string. Here's a hack to make it work. Change line 62 to:
a = a.strip().encode('utf8')
#
Using the "with" keyword, this functionality is now included in the Django distribution. See http://stackoverflow.com/questions/2111555/django-templates-changing-context-for-an-include-template a (at least) two examples.
#