Для переменной цикла, используемой в templatetag? - PullRequest
4 голосов
/ 12 апреля 2010

Попытка решить проблему с тегами-шаблонами.

У меня есть два тега шаблона:

@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.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)

И я хочу использовать их так:

{% for letter in letters %}
<h2>{{ letter }}</h2>
{% get_names for letter as names %}
<ul>
    {% for name in names %}
    <li>{{ name }}</li>
    {% endfor %}
</ul>
{% endfor %}

Но «письмо» отправляется как слово «буква», а не как буква, которую должна содержать переменная. Есть ли способ обойти это или я что-то упустил (или, что еще лучше, пакет, который уже делает это)?

1 Ответ

4 голосов
/ 12 апреля 2010

Вы получаете строку "letter", потому что это то, что анализатор шаблонов прочитал из вашего источника шаблона. Если вы хотите получить доступ к значению этой переменной, вы должны пометить его как переменную шаблона в NameNode.__init__ и разрешить , используя контекст в render.

Как следует:

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 ''

Это объясняется в документах здесь .

...