The best way to divide card-deck into rows in django template - django

What I have(image)
So i need to divide these cards into 4-5 cards per row.
My solution is simple
<div class="card-deck">
{% for book in books %}
{% include 'books/book_element.html' %}
{% endfor %}
</div>
And I have tried for a while and was doing some brainstorm
{% for book in books %}
{% if forloop.counter|divisibleby:"5" or forloop.counter == 1 %}
<div class="card-deck">
</div>
{% endif %}
{% endfor %}
How can I include a template into a div.card-deck?

You need to close the previous row and open a new one in your loop. Something like this:
<div class="card-deck">
{% for book in books %}
{% include 'books/book_element.html' %}
{% if forloop.counter|divisibleby:"5" %}
{# Close the current deck and start a new one %}
</div><div class="card-deck">
{% endif %}
{% endfor %}
</div><!-- The final deck is closed here, outside the loop -->

Related

Getting the last for loop iteration of condition in django templates

I wish to add the class rounded-t-lg shadowon the first iteration inside the if statement, and rounded-b-lg shadow on the last iteration. I have the following code:
{% for note in notes %}
{% if note.is_sticky %}
<div class="flex items-center">
<div class="{% if forloop.first %} rounded-t-lg shadow {% elif forloop.last %} rounded-b-lg shadow {% endif %}">
<!-- code -->
</div>
</div>
</div>
{% endif %}
{% endfor %}
The problem that I'm running into is that forloop.last applies to the last iteration in general, and not the last iteration in the condition. So if I have three objects, where two is sticky, and the last one is not, the class will be applied to the one that is not, since its the last in "line".
How can I apply a class to the last iteration within the is_sticky condition, regardless of the objects that do not meet the condition?
Ideally you should filter the notes list in your view, so it only contains those where is_sticky == True. Depending on your queryset you may just need to add:
.filter(is_sticky=True)
I also think you might need to be careful of the case when there is only 1 element in notes. I guess you want it to be rounded top and bottom, so you need 2 separate if tests, rather than an elsif.
{% for note in notes %}
<div class="flex items-center">
<div class="{% if forloop.first %} rounded-t-lg shadow{% endif %}{% if forloop.last %} rounded-b-lg shadow{% endif %}">
<!-- code -->
</div>
</div>
{% endfor %}
This should work:
{% for note in notes %}
{% if forloop.first %}
{% if note.is_sticky %}
<div class="flex items-center">
<div class="rounded-t-lg shadow">
<!-- code -->
</div>
</div>
</div>
{% endif %}
{% elif forloop.last %}
{% if note.is_sticky %}
<div class="flex items-center">
<div class="rounded-b-lg shadow">
<!-- code -->
</div>
</div>
</div>
{% endif %}
{% endif %}
{% endfor %}

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

How can I check for loop count? (and whether it is even or odd) [duplicate]

This question already has answers here:
How do I get odd and even values in a Django for loop template?
(4 answers)
Closed 8 years ago.
{% for p in posts %}
<div id="even">{{ p.title }}</div>
<div id="odd">{{ p.title }}</div>
{% endfor %}
I need create something like this:
{% for p in posts %}
{% if forloop_count is even %}
<div id="even">{{ p.title }}</div>
{% else %}
<div id="odd">{{ p.title }}</div>
{% endif %}
{% endfor %}
How can I check for loop count? (and whether it is even or odd)
Is that your real underlying requirement, or are you simply trying to cycle between two div classes? Do they have to be odd/even, or just alternating?
{% for o in some_list %}
<tr class="{% cycle 'row1' 'row2' %}">
...
</tr>
{% endfor %}
Reference: https://docs.djangoproject.com/en/dev/ref/templates/builtins/
In your case it would be:
{% for p in posts %}
<div id="{% cycle 'even' 'odd' %}">{{ p.title }}</div>
{% endif %}
Use divisableby
{% for p in posts %}
{% if forloop.counter|divisibleby:"2" %} {# is even #}
<div id="even">{{ p.title }}</div>
{% else %}
<div id="odd">{{ p.title }}</div>
{% endif %}
{% endfor %}
or if its simply for a id use cycle e.g.
{% cycle 'odd' 'even' %}