- Author:
- limodou
- Posted:
- February 25, 2007
- Language:
- Python
- Version:
- Pre .96
- Score:
- 10 (after 10 ratings)
I knew that template in myght template system can receive some parameters just like a function. And I also want to implement this function in django template. So I finish a rough one, the code is pasted here. It just like include, but in order to distinguish with "include" tag, I call it "call". So you can use it:
{% call "some.html" %}
This way just like include tag, and the advanced way:
{% call "some.html" with "a" "b"|capfirst title="title1" %}
{% call "some.html" with "c" "d" title="title2" %}
So you can see, "call" tag can do like a python function, it can receive tuple parameters and key word parameters, just like the function:
def func(*args, **kwargs):pass
How to use it
test_call.html
{% expr "limodou" as name %}
{% call "test/test_sub.html" with "a"|capfirst "b" title="title1" %}<br/>
{% call "test/test_sub.html" with "c" "d" title="title2" %}
expr is also a custom tag written by me. It'll calculate a python expression and save to result to a variable. In this case, the variable it "name".
test_sub.html
{% for i in args %}{{ i }}{% endfor %}
<h2>{{ title }}</h2>
<p>{{ name }}</p>
<h3>args</h3>
{{ args }}
<h3>kwargs</h3>
{{ kwargs }}
And you also can see, call tag will auto create args and kwargs context variables.
I hope this will be some useful.
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)
|
More like this
- Template tag - list punctuation for a list of items by shapiromatron 11 months, 1 week ago
- JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 2 weeks ago
- Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
- Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
- Help text hyperlinks by sa2812 1 year, 7 months ago
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')
#
Please login first before commenting.