在Django中解析形式标签中的forloop.counter

时间:2015-09-16 18:24:23

标签: django django-forms django-templates

我试图通过循环生成的某些表单的标签取决于forloop.counter,但是没有成功。这就是我到目前为止所做的:

{% for field in form %}

{% formfield field with label="blablabla {{ forloop.counter }}" %}

{% endfor %}

这将返回正确的表单,但{{forloop.counter}}显示在标签中,而不是由其值替换。

我做错了什么?我在Django代码中到处都看到这种结构,例如:在https://docs.djangoproject.com/en/1.4/intro/tutorial04/

<h1>{{ poll.question }}</h1>

{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}

<form action="/polls/{{ poll.id }}/vote/" method="post">
{% csrf_token %}
{% for choice in poll.choice_set.all %}
    <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}" />
    <label for="choice{{ forloop.counter }}">{{ choice.choice }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>

在上面的示例中,除了id之外,什么设置了“标签”,这使得无法将{{ forloop.counter }}解析为字符串?

1 个答案:

答案 0 :(得分:1)

我们无法在另一个Django标记{{ }}中使用{% %}使用Django变量。

Django在其文档中未在模板标记{{ }}内的任何位置使用{% %}。它到处都是单独使用它。

例如:

以下2个代码段有效。

{% firstof var1 var2 var3 %} # valid
<li> {{ some_variable }} </li> # valid

但是,此代码段无效。

{% firstof var1 var2 {{some_var}} %} # invalid

那么可以做些什么?

我们知道模板标签{% %}中可以分配模板中已存在的变量。因此,如果我们事先计算变量my_label,那么我们可以直接在模板标记中分配此变量。

{% formfield field with label=my_label %} # our target

因此,我们需要计算值"blablabla<x>",其中xforloop.counter的值,并将其存储在变量my_label中。

计算并将label值存储在单独的变量中

要在变量中存储值,我们可以使用内置的with模板标记。

我们可能会尝试使用以下行计算my_label变量,但由于我们再次在模板标记中使用相同的变量语法,因此会导致错误。

{% with my_label="blablabla{{forloop.counter}}" %} # invalid

所以,我们现在需要以不同的方式解决问题。我们必须将choice连接到forloop.counter的值以获取blablabla1blablabla2等等,我们知道存在模板过滤器add,它会添加对价值的论证。我们可以使用这个过滤器。

因此,我们尝试以下代码。

{% with my_label="blablabla"|add:forloop.counter %} # will still not work 

但这仍然无法解决我们的问题。当我们尝试使用字符串''添加整数my_label时,空字符forloop.counter将分配给"blablabla"变量。在使用字符串添加整数时,将引发错误,如果出现错误,Django将为其分配一个空字符串。

根据add filter上的文档:

  

此过滤器将首先尝试将两个值强制转换为整数。如果这   失败了,无论如何它都会尝试将值加在一起。这会奏效   对某些数据类型(字符串,列表等)而在其他数据类型上失败。如果它   失败,结果将是一个空字符串。

因此,我们需要先将forloop.counter的值转换为字符串,然后将其存储在变量counter_value中。这可以使用stringformat内置模板过滤器完成。然后我们可以使用add过滤器。

{% with counter_value=forloop.counter|stringformat:"s" %}  # assign counter value to a variable
{% with my_label="blablabla"|add:counter_value %} # compute value of 'my_label'

现在,我们拥有my_label的价值,我们可以使用它来获得所需的结果。

{% formfield field with label=my_label %} # use your label variable here

最终代码:

{% for field in form %}

    {% with counter_value=forloop.counter|stringformat:"s" %} 
    {% with my_label="blablabla"|add:counter_value %} 
    {% formfield field with label=my_label %}
    {% endwith %}
    {% endwith %}

{% endfor %}

注意:我正在尝试稍微不同的代码版本,而不是最初发布的答案(如下所示),这不会导致OP出错。感谢@Daniel纠正错误。

之前发布的答案,即以下代码在Django标记{% %}中不能用作,我们无法放置{{ }}

# this initially posted code won't work
{% formfield field with label='blablabla {{ forloop.counter|stringformat:"s" }}' %}