在Django模板中动态创建列表

时间:2010-09-15 07:33:58

标签: django django-templates

我不知道是否可能,但我希望能够写出如下内容:

{% with var1 var2 var3 as some_list %}
    {{ some_list|maximum }}
{% endwith %}

从任意数量的模板变量和/或文字中动态创建列表似乎很有用,所以我希望我忽略了一些简单的事情。

如果不这样做,我想知道如何创建一个接受任意数量参数的模板标签。 (我玩过simple_tag,它适用于接受固定数量参数的标签。)

在确定没有更简单的解决方案之前,我不想去创建解析器和继承django.template.Node的麻烦。

2 个答案:

答案 0 :(得分:15)

如果您想添加新变量(即some_list),则需要访问模板的上下文,因此simple_tag是不够的。

对我来说,第一种方法是尝试在视图中执行此类工作,以使模板尽可能简单。

如果这不合适,您必须手动编写标签,如下所示:

@register.tag
def make_list(parser, token):
  bits = list(token.split_contents())
  if len(bits) >= 4 and bits[-2] == "as":
    varname = bits[-1]
    items = bits[1:-2]
    return MakeListNode(items, varname)
  else:
    raise template.TemplateSyntaxError("%r expected format is 'item [item ...] as varname'" % bits[0])

class MakeListNode(template.Node):
  def __init__(self, items, varname):
    self.items = map(template.Variable, items)
    self.varname = varname

  def render(self, context):
    context[self.varname] = [ i.resolve(context) for i in self.items ]
    return ""

并像这样使用它来创建一个新变量some_list

{% make_list var1 var2 var3 as some_list %}

随意给它一个更好的名字!

答案 1 :(得分:3)

我玩了一下,想出了一个可以接受可变数量的参数并将它们转换成列表的标签。

@register.tag('to_list')
def to_list(_parser, token):
    try:
        parts = token.split_contents()
    except ValueError:
        raise template.TemplateSyntaxError, \
          "%r tag requires at least one argument" % token.contents.split()[0]

    return AsListNode(parts[1:])

class AsListNode(template.Node):
    def __init__(self, parts):
        self.parts = map(lambda p: template.Variable(p), parts)

    def render(self, context):
        resolved = []
        for each in self.parts:
            resolved.append(each.resolve(context))
        return resolved

模板:

<p>{% to_list var1 var2 var3 %}</p>

<强>更新

@ Will solution更好。它允许您使用另一个变量保存结果列表,以便以后可以对其进行操作。