Ad

Django - Variable Cached With "with" Template Tag Isn't Evaluated

- 1 answer

I'm following along this article, and I have a form like this:

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

I figured, since there are multiple instances of "choice{{ forloop.counter }}", I can cache it with with template tag and use it as a variable. But as you can see, the variable forloop.counter inside the with template tag isn't evaluated.

not expected

The expected result was this:

expected result

How can I fix this?

Ad

Answer

The variable using {{ }} cannot be used inside {% %}Built-in tag[Django-doc] but we can use the variable inside {% %} if it is already available in the template. So we have to get the value before and we can set that value using with[Django-doc]. But the value you are getting is dynamic with every loop you get new value with {{forloop.counter}} and the same thing we cannot use {{ }} inside {% %}.So you can concatenate the values differently i.e. {{forloop.counter}} and choice. For concatenate we can use add Built-in filter[Django-doc] as documented

Adds the argument to the value. 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.

But the problem with add is as Warned as

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

So we have to convert the {{forloop.counter}} to string first before concatenation and we can use stringformat[Django-doc] for that and store the value and use that value as

{% 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 %}
Ad
source: stackoverflow.com
Ad