在 Django 的表单标签中解析 forloop.counter

Parsing forloop.counter in form's label in Django

我试图使我通过循环生成的某些表单的标签依赖于 forloop.counter,但没有成功。这是我目前所拥有的:

{% for field in form %}

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

{% endfor %}

此 returns 是正确的形式,但 {{ 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 }} 解析为字符串?

我们不能在另一个 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

所以,我们现在需要以不同的方式处理这个问题。我们必须将 choiceforloop.counter 的值连接起来以获得 blablabla1blablabla2 等等,我们知道存在一个模板过滤器 add,它添加了值的参数。我们可以使用这个过滤器。

所以,我们试试下面的代码。

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

但这仍然不能解决我们的问题。一个空字符串 '' 将被分配给 my_label 变量,因为我们试图将一个整数 forloop.counter 与字符串 "blablabla" 相加。在将整数与字符串相加时,将引发错误,如果出现错误,Django 将为其分配一个空字符串。

根据 add filter 上的文档:

This filter will first try to coerce both values to integers. If this fails, it’ll attempt to add the values together anyway. This will work on some data types (strings, list, etc.) and fail on others. If it fails, the result will be an empty string.

所以,我们需要先将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" }}' %}