Django template - for loop and then if statement - django

I have this loop:
<div class="product-gallery-preview order-sm-2">
{% for images in Artikel.productimages_set.all %}
{% if images.Position == 1 %}
<div class="product-gallery-preview-item active" id="gallery{{ images.Position }}">
{% else %}
<div class="product-gallery-preview-item" id="gallery{{ images.Position }}">
the problem is that all div classes are active I think because it's true for the first picture which is found.
Is it possible to go in the loop check all pictures if it is in Position 1 and just output the div box I tried to print?

You can use forloop.counter...
{% if forloop.counter == 1 %}
<div class="product-gallery-preview-item active" id="gallery{{ images.Position }}">
{% else %}
....
{% endif %}

Related

Add html code if the element is first in query - Django

In the Bootstrap slider, the first element has the value "active", how to check and add this value to the html code for the queryset, if element is first.
Example (which is not working):
{% for obj in query %}
<div class="carousel-item {% if query|first %}active{% endif %}">
[...]
</div>
{% endfor %}
*this gives activity for all items, not just the first. Expected result is only for first.
You can work with forloop.first [Django-doc] to check if it is the first element, so:
{% for obj in query %}
<div class="carousel-item{% if forloop.first %} active{% endif %}">
[...]
</div>
{% endfor %}
The forloop.first will return:
True if this is the first time through the loop
You can use forloop.counter like this:
{% for obj in query %}
<div class="carousel-item {% if forloop.counter == 1 %} active {% endif %}">
[...]
</div>
{% endfor %}
forloop.counter is 1 index based counter used to store current index of the loop.

How to split a menu within a wagtail model?

I'm trying to create a navigation menu, that when the number of objects within the menu is even puts an image between the two halves of the menu. Here is the code that I tried to use within my menu model and templates to create the effect.
"""Splitting the menu in half for the frontend."""
#property
def is_even(self):
if (self.objects.count() % 2) == 0:
return True
else:
return False
#property
def find_halves(self):
first_half = self.objects[0:self.objects.count()/2]
second_half = self.objects[self.objects.count()/2:self.objects.count()]
return first_half, second_half
<nav class="main-nav">
{% image navigation.logo fill-115x115 as logo %}
<ul class="nav-links">
{% if navigation.is_even %}
{% for item in navigation.menu_items.first_half.all %}
<li><a href="{{ item.link }}" {% if item.open_in_new_tab %} target="_blank" {% endif %}>{{ item.title }}</a></li>
{% endfor %}
<img src="{{ logo.url }}" alt="CCCR Logo" class="logo">
{% for item in navigation.menu_items.second_half.all %}
<li><a href="{{ item.link }}" {% if item.open_in_new_tab %} target="_blank" {% endif %}>{{ item.title }}</a></li>
{% endfor %}
{% else %}
<img src="{{ logo.url }}" alt="CCCR Logo" class="logo">
{% for item in navigation.menu_items.all %}
<li><a href="{{ item.link }}" {% if item.open_in_new_tab %} target="_blank" {% endif %}>{{ item.title }}</a></li>
{% endfor %}
{% endif %}
</ul>
</nav>
However, when I run the code it goes to the else statement even though I have six menu items in the wagtail admin.
For an item like this that is related to what users see, I would suggest using the Django template tag divisibleby: https://docs.djangoproject.com/en/3.0/ref/templates/builtins/#divisibleby
So maybe something like this:
{% if navigation.menu_items.count|divisibleby:"2" %}
You might also find the cycle template tag useful. It might let you do what you want layout-wise by alternating the placement of a class on odd and even items.

If statement in my Django template...Is there a better way?

In my Django template: I'm trying to add an extra div around my for loop only if the length of the data being passed to the template is 3. This is what I'm trying right now but it seems like there could be better way than doing two if statements to check for the length:
{% if items|length == 3 %}
<div class='three-item-wrap'>
{% endif %}
{% for item in items %}
.......
{% endfor %}
{% if items|length == 3 %}
</div> //close .three-item-wrap
{% endif %}
you can try like that
{% if items|length == 3 %}
<div class='three-item-wrap'>
{% for item in items %}
.......
{% endfor %}
</div>
{% else %}
#another logic goes here
{% endif %}
if you want know more refer the docs django if tempalate
I think better way would be to make single if statement check. Just like this:
{% if items|length == 3 %}
<div class='three-item-wrap'>
{% for item in items %}
.......
{% endfor %}
</div>
{% else %}
{% for item in items %}
.......
{% endfor %}
{% endif %}
This way is better because of Django render engine, which firstly check if statements and then do for loop.
And if something crash in your code, div will be without closing tag </div>. Instead in my code there is no option for div to be without closing tag.

Django template skip line every two iteration

I have the following html structure:
<div class="row>
<div class="box"></div>
<div class="box"></div>
</div>
I am using pagination feature on Django to pass on 6 items per page.
How would I go about iterating over the paginator generated object list while wrapper each two box divs with row div?
You can use the forloop.counter in the template
{% for obj in obj_list %}
{% if forloop.counter0|divisibleby:2 %}
<div class="row">
{% endif %}
<div class="box"></div>
<div class="box"></div>
{% if forloop.counter|divisibleby:2 %}
</div>
{% endif %}
{% else %}
Nothing to show
{% endfor %}
and if there are odd number of elements in the list, then it would not have a trailing div. I will let you figure out that scenario by yourself. (it is pretty simple)
Documentation for the forloop.counter0 can be found here
Documentation for divisibleby can be found here
I agree with karthikr's solution, but it doesn't print the </div> if you have 3, 5 items...
You have to add a forloop.last to handle that case:
{% for obj in obj_list %}
{% if forloop.counter0|divisibleby:2 %}
<div class="row">
{% endif %}
<div class="box"></div>
<div class="box"></div>
{% if forloop.counter|divisibleby:2 or forloop.last %}
</div>
{% endif %}
{% else %}
Nothing to show
{% endfor %}

Django create multi colums flexible best practices

I want to create a picture viewer with many colums. I don' know exactly the number.
I want to respect best practices.
I have done the following code :
{% with max=4 taille=3 %}
{% for image in image_list %}
{% if nb == 1 %}
<div class="row">
{% endif %}
<div class="col-sm-{{ taille }}">
{{ image.name }}
</div>
{% if nb == 2 %}
</div>
{% endif %}
{% nb += 1 %}
{% if nb > 4 %}
{% nb = 1 %}
{% endif %}
{% endfor %}
{% endwith %}
But the templating system don't allow me to do this line :
{% nb += 1 %}
Do you have any ideas ? Thank you.
This is a quick example on how you can do this (this is for 2 column based itteration) but you can change it to your liking (replace "2" with a integer for instance):
<div class="row">
{% for image in image_list %}
<div class="col-sm-6">
{{ image.name }}
</div>
{% if not forloop.last and forloop.counter|divisibleby:"2" %}
</div>
<div class="row">
{% endfor %}
</div>
In Django Templates you can not use += 1 operator
you can use the forloop.counter
{% if forloop.counter0|divisibleby:4 %} so every 4 iterations
starting with first iteration where
counter is 0
<div class="row">
{% endif %}
<div class="col-sm-{{ taille }}">
{{ image.name }}
</div>
{% if forloop.counter0|add:"-1"|divisibleby:"4" %} also every 4 iterations
but starting with the 2nd
iteration where counter is 1
</div>
{% endif %}