Reputation: 393
I have a django template where I need to cycle through a set of background colours across two different for loops. The cycle tag seems to be designed to be used either within one for loop or outside a for loop altogether. This is my code:
{% if global_adverts %}
<span style="display:none">{% cycle 'advert-grey' 'advert-pale-blue' 'advert-green' 'advert-blue' as adcolors %}</span>
{% for advert in global_adverts %}
<div class="{% cycle adcolors %}">
{% if advert.url %}<a href="{{ advert.url }}">{% endif %}
<p>{{ advert.text }}</p>
{% if advert.url %}</a>{% endif %}
</div>
{% endfor %}
{% endif %}
{% with self.adverts.all as adverts %}
{% if adverts %}
{% for advert in adverts %}
<div class="{% cycle adcolors %}">
{% if advert.url %}<a href="{{ advert.url }}">{% endif %}
<p>{{ advert.text }}</p>
{% if advert.url %}</a>{% endif %}
</div>
{% endfor %}
{% endif %}
{% endwith %}
Is there a way to do this without outputting the first item in the cycle before the first loop and having to hide it with css?
Upvotes: 2
Views: 772
Reputation: 376
I feel that having the first {% cycle %}
declaration outside of the loops is cleaner, I wouldn't have expected a declaration inside of conditional loops to work, and here's how to make it work:
{% cycle 'advert-grey' 'advert-pale-blue' 'advert-green' 'advert-blue' as adcolour silent %}
{% if global_adverts %}
{% for advert in global_adverts %}
<div class="{{ adcolours }}">
{% if advert.url %}<a href="{{ advert.url }}">{% endif %}
<p>{{ advert.text }}</p>
{% if advert.url %}</a>{% endif %}
</div>
{% cycle adcolours %}
{% endfor %}
{% endif %}
{% with self.adverts.all as adverts %}
{% if adverts %}
{% for advert in adverts %}
<div class="{{ adcolours }}">
{% if advert.url %}<a href="{{ advert.url }}">{% endif %}
<p>{{ advert.text }}</p>
{% if advert.url %}</a>{% endif %}
</div>
{% cycle adcolour %}
{% endfor %}
{% endif %}
{% endwith %}
Since {% cycle adcolour %}
is silent, we use {{ adcolour }}
to print the current colour. We still need to use the silent {% cycle adcolour %}
to step through the colours on each iteration.
Upvotes: 0
Reputation: 393
I have discovered that the following code gives the desired result:
{% if global_adverts %}
{% for advert in global_adverts %}
<div class="{% cycle 'advert-grey' 'advert-pale-blue' 'advert-green' 'advert-blue' as adcolours %}">
{% if advert.url %}<a href="{{ advert.url }}">{% endif %}
<p>{{ advert.text }}</p>
{% if advert.url %}</a>{% endif %}
</div>
{% endfor %}
{% endif %}
{% with self.adverts.all as adverts %}
{% if adverts %}
{% for advert in adverts %}
<div class="{% cycle adcolours %}">
{% if advert.url %}<a href="{{ advert.url }}">{% endif %}
<p>{{ advert.text }}</p>
{% if advert.url %}</a>{% endif %}
</div>
{% endfor %}
{% endif %}
{% endwith %}
Upvotes: 1
Reputation: 5256
Just add silent
{% cycle 'advert-grey' 'advert-pale-blue' 'advert-green' 'advert-blue' as adcolors silent %}
It prevents the tag from outputting the value
EDIT AFTER COMMENT
If you need the cycle to continue for each loop just use cycle twice and change the order of the items in the second cycle:
{% if global_adverts %}
{% for advert in global_adverts %}
<div class="{% cycle 'advert-grey' 'advert-pale-blue' 'advert-green' 'advert-blue' %}">
{% if advert.url %}<a href="{{ advert.url }}">{% endif %}
<p>{{ advert.text }}</p>
{% if advert.url %}</a>{% endif %}
</div>
{% endfor %}
{% endif %}
{% with self.adverts.all as adverts %}
{% if adverts %}
{% for advert in adverts %}
<div class="{% cycle 'advert-pale-blue' 'advert-green' 'advert-blue' 'advert-grey' %}">
{% if advert.url %}<a href="{{ advert.url }}">{% endif %}
<p>{{ advert.text }}</p>
{% if advert.url %}</a>{% endif %}
</div>
{% endfor %}
{% endif %}
{% endwith %}
Upvotes: 1