Trying to solve a problem with templatetags.
I have two templatetags:
@register.inclusion_tag('directory/_alphabet.html')
def alphabet_list(names):
""" Return a list of letters that last names start with. """
return { 'letters': [name.last_name[0] for name in names] }
class NameNode(template.Node):
def __init__(self, letter, var_name):
self.letter = letter
self.var_name = var_name
def render(self, context):
context[self.var_name] = Person.objects.get_active().filter(
last_name__istartswith=self.letter)
return ''
@register.tag
def get_names(parser, token):
try:
tag_name, arg = token开发者_Python百科.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError, "%r tag requires arguments" % \
token.contents.split()[0]
m = re.search(r'for (.*?) as (\w+)', arg)
if not m:
raise template.TemplateSyntaxError, "%r tag had invalid arguments" % \
tag_name
letter, var_name = m.groups()
return NameNode(letter, var_name)
And I want to use them like so:
{% for letter in letters %}
<h2>{{ letter }}</h2>
{% get_names for letter as names %}
<ul>
{% for name in names %}
<li>{{ name }}</li>
{% endfor %}
</ul>
{% endfor %}
But 'letter' gets sent as the word 'letter' and not as whatever letter the variable should contain. Is there a way around this or something I'm missing (or, better yet, a package that already does this)?
You get the string "letter"
because this is what the template parser read from your template source. If you want to access the value of this variable, you have to mark it as a template variable in NameNode.__init__
and resolve it using the context in render
.
As follow:
class NameNode(template.Node):
def __init__(self, letter, var_name):
self.letter = template.Variable(letter)
self.var_name = var_name
def render(self, context):
try:
context[self.var_name] = Person.objects.get_active().filter(
last_name__istartswith=self.letter.resolve(context))
except template.VariableDoesNotExist:
pass
return ''
It's explained in the docs here.
精彩评论