Django - Переменная, кэшируемая тегом шаблона "with", не оценивается

Я следую этой статье, и у меня есть такая форма:

<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
<fieldset>
    <legend><h1>{{ question.question_text }}</h1></legend>
    {% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
    {% for choice in question.choice_set.all %}
        <input type="radio" name="choice" id="choice{{ forloop.counter }}" value="{{ choice.id }}">
        <label for="choice{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
    {% endfor %}
</fieldset>
<input type="submit" value="Vote">
</form>

Я подумал, что поскольку существует несколько экземпляров "choice{{ forloop.counter }}", я могу кэшировать его с помощью тега шаблона with и использовать его как переменную. Но, как вы видите, переменная forloop.counter внутри шаблонного тега with не оценивается.

not expected

Ожидаемый результат был следующим:

expected result

Как я могу это исправить?

Переменная, использующая {{ }}, не может быть использована внутри {% %}Built-in tag[Django-doc], но мы можем использовать variable внутри {% %}, если она уже доступна в шаблоне. Поэтому мы должны получить значение раньше и можем установить его с помощью with[Django-doc]. Но значение, которое вы получаете, является динамическим, с каждым циклом вы получаете новое значение с помощью {{forloop.counter}} и то же самое мы не можем использовать {{ }} внутри {% %}. Поэтому вы можете конкатенировать значения по-другому, т.е. {{forloop.counter}} и choice. Для concatenate мы можем использовать add Built-in filter[Django-doc] как документировано

Добавляет аргумент к значению. Этот фильтр сначала попытается привести оба значения к целым числам. Если это не удастся, он все равно попытается сложить значения. Это сработает для некоторых типов данных (строки, список и т.д.) и не сработает для других.

Но проблема с add такая же Warned как и

Strings that can be coerced to integers will be summed, not concatenated,

Поэтому перед конкатенацией нам нужно сначала преобразовать {{forloop.counter}} в строку, для чего мы можем использовать stringformat[Django-doc], сохранить значение и использовать его как

{% for choice in question.choice_set.all %}
    {% with counter=forloop.counter|stringformat:"s" %} 
    {% with choice_id="choice"|add:counter %}
    <input type="radio" name="choice" id={{choice_id}} value="{{ choice.id }}">
    <label for={{choice_id}}>{{ choice.choice_text }}</label><br>
    {% endwith %}
    {% endwith %}
{% endfor %}
Вернуться на верх