开发者

For loop variable used in templatetag?

开发者 https://www.devze.com 2022-12-26 07:44 出处:网络
Trying to solve a problem with templatetags. I have two templatetags: @register.inclusion_tag(\'directory/_alphabet.html\')

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消