Django: Forloop Counter 0 divisible by 3 not working properly - django

PLATFORM: Django
Problem
When using {% forloop.counter0|divisibleby:3 %} it doesn't seem to properly divide out? I can't quite tell what's going on.
Goal
Display an Avery HTML template with pre-populated info from the database. 3 column table with variable rows.
Code
<table>
{% for job in jobsite %}
{% if forloop.counter0|divisibleby:3 %}<tr>{% endif %}
<td>{{ job.name }}<br/>{{ job.address }}<br/>{{ job.address_2 }}{% if job.address_2 %}<br/>{% endif %}{{ job.city }}, {{ job.state }} {{ job.zip }}</td>
{% if forloop.counter < 3 %}
<td class="spacer" rowspan="0"> </td>
{% endif %}
{% if forloop.counter0|divisibleby:3 or forloop.last %}<tr>{% endif %}
{% endfor %}
</table>
Why is this failing?
Additional Info
I can get close if I change the code around to the following. The problem then becomes that counter 2 is blank. If I fill in data, it's duplicated (row 1 column 2, row 1 column 3):
<table>
<tr>
{% for job in jobsite %}
{% if forloop.counter|divisibleby:3 %}</tr><tr>{% endif %}
<td>{{ job.name }}<br/>{{ job.address }}<br/>{{ job.address_2 }}{% if job.address_2 %}<br/>{% endif %}{{ job.city }}, {{ job.state }} {{ job.zip }}</td>
{% if forloop.counter < 3 %}
<td class="spacer" rowspan="0"> </td>
{% endif %}
{% if forloop.counter == 2 %}
<td></td>
{# <td>{{ job.name }}<br/>{{ job.address }}<br/>{{ job.city }}, {{ job.state }} {{ job.zip }}</td>#}
{% endif %}
{% endfor %}
</table>
Close to the desired display

Problem When using {% if forloop.counter0|divisibleby:3 %} it doesn't seem to properly divide out? I can't quite tell what's going on.
The forloop.counter0 will count with 0, 1, 2, 3, …. This means that the first cycle will already satisfy the condition, since 0 is dividably by 3 (and by any number), so it will already apply the "split logic" for the first cycle. forloop.counter on the other hand will count with 1, 2, 3, 4, … so the first iteration where it will add a line is the third one.
You can work with:
<table>
<tr>
{% for job in jobsite %}
<td>{{ job.name }}<br/>{{ job.address }}<br/>{{ job.address_2 }}{% if job.address_2 %}<br/>{% endif %}{{ job.city }}, {{ job.state }} {{ job.zip }}</td>
{% if forloop.counter|divisibleby:3 and not forloop.last %}
</tr><tr>
{% elif not forloop.last %}
<td class="spacer" rowspan="0"> </td>
{% endif %}
{% endfor %}
</tr>
</table>

I did not find a solution to this specific challenge, however I redesigned it primarily relying on CSS instead of table layout. Code as follows "solves" the challenge.
{% for job in jobsite %}
<div class="address-label">{{ job.name }}<br/>{{ job.address }}<br/>{{ job.address_2 }}{% if job.address_2 %}<br/>{% endif %}{{ job.city }}, {{ job.state }} {{ job.zip }}</div>
{% endfor %}

Related

How to display multiple object data in html table in django template

I passed two queryset objects from views to template both have product data with its features now the main problem is how to show this both objects data simultaneously in HTML table?
table structure:
features1 | product1 features value 1 | product2 feature value 1
features2 | product1 features value 2 | product2 feature value 2
...
<tbody>
{% for a in product_data %}{% for b in product_data_2 %}
<tr class="row" style="line-height: 3">
{% if forloop.counter == forloop.parentloop.counter %}
{% for feature_data in a.product_features.all %}{% for feature_data_1 in b.product_features.all %}
<td class="col-lg-4 col-md-4 col-sm-4 col-4" style="text-align: left; font-weight: bold;">
{{ feature_data.feature.feature_name }}
</td>
<td class="col-lg-4 col-md-4 col-sm-4 col-4" style="text-align: center;">
{{ feature_data.product_feature_value }}
</td>
<td class="col-lg-4 col-md-4 col-sm-4 col-4" style="text-align: center;">
{{ feature_data_1.product_feature_value }}
</td>
{% endfor %}{% endfor %}
{% elif forloop.counter < forloop.parentloop.counter %}
something
{% elif forloop.parentloop.counter < forloop.counter %}
something
{% endif %}
</tr>
{% endfor %}{% endfor %}
</tbody>
please try to answer i tried but nothing work
Depending on your purpose you can use access by index and with:
{% with first_obj=product_data.0 %}
{% with second_obj=product_data.1 %}
...
{% for feature_data in first_obj.product_features.all %}
...
{% endfor %}
{% for feature_data in second_obj.product_features.all %}
...
{% endfor %}

No named cycles in template. 'row1,row2' is not defined

In my django inline formset, form html:
{% block body %}
<h2>Profile</h2>
<hr>
<div class="col-md-4">
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<table class="table">
{{ familymembers.management_form }}
{% for form in familymembers.forms %}
{% if forloop.first %}
<thead>
<tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}</th>
{% endfor %}
</tr>
</thead>
{% endif %}
<tr class="{% cycle row1,row2 %} formset_row">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
<input type="submit" value="Save"/> back to the list
</form>
</div>
{% endblock %}
When I tried to open form it gives
TemplateSyntaxError at /profile/add/
No named cycles in template. 'row1,row2' is not defined
How could I avoid this error?
That's not how you use that tag, as the docs show. The values should be separated by spaces, not commas, and if they are literal strings they should be in quotes.
{% cycle "row1" "row2" %}
If you still get an error, you can try:
class="{% cycle 'row1' 'row2' %} formset_row"

How to I get the length or size or number of fields in a form in a django template?

I would like to write a loop like this, so that I can spread the form fields out in a table. :
{% load widget_tweaks %}
{% load mathfilters %}
{% load get_range %}
{% for k in form|length|div:5|floatformat|add:1|get_range %}
<tr>
{% for field in form %}
{% if forloop.counter >= k|mul:5 and forloop.counter <= k|mul:5|add:4 %}
<th>{{ field.label_tag }}{{ field.errors }}</th>
{% endif %}
{% endfor %}
</tr>
<tr>
{% for field in form %}
{% if forloop.counter >= k|mul:5 and forloop.counter <= k|mul:5|add:4 %}
<td>{{ field|add_class:"span4" }}</td>
{% endif %}
{% endfor %}
</tr>
{% endfor %}
This doesn't work, but because the code above fails on form|length. In order for this to work, I need to get, in a template, the number of fields in a form. Does anyone know how to do this? I've searched all over but can't find anything. The following do NOT work:
form.len
form.length
form|length
Thanks!
I'm really not sure what you are looking for, but it sounds like this:
{% for field in form %}
<tr>
{% if forloop.counter0|divisibleby:5 %}
<th class="span4">{{ field.label_tag }}{{ field.errors }}</th>
{% else %}
<th>{{ field.label_tag }}{{ field.errors }}</th>
{% endif %}
</tr>
{% endfor%}
{% for field in form %}
<tr>
{% if forloop.counter0|divisibleby:5 %}
<td>{{ field|add_class:"span4" }}</td>
{% else %}
<td>{{ field }}</td>
</tr>
{% endfor %}
I dont like this code, but it was my first idea.
{% for field in form %}
{% if forloop.last %}
{{ forloop.counter }}
{% endif %}
{% enfor %}
form.fields I believe.
{% for field_name in form.fields %}
thanks for your suggestions - they helped! Here is what finally worked for me:
{% for field in form %}
{% if forloop.counter0|divisibleby:5 %}
<tr>
{% for field in form %}
{% if forloop.counter0 >= forloop.parentloop.counter0 and forloop.counter0 <= forloop.parentloop.counter0|add:4 %}
<th>{{ field.label_tag }}{{ field.errors }} </th>
{% endif %}
{% endfor %}
</tr>
<tr>
{% for field in form %}
{% if forloop.counter0 >= forloop.parentloop.counter0 and forloop.counter0 <= forloop.parentloop.counter0|add:4 %}
<td>{{ field }}</td>
{% endif %}
{% endfor %}
</tr>
{% endif %}
{% endfor %}

Custom formset templates in Django

I am using a Django formset for this model:
class Book(models.Model):
book_id=models.AutoField(primary_key=True,unique=True)
book_name=models.CharField(max_length=30)
publisher_name=models.CharField(max_length=40)
author=models.ForeignKey(Author)
The formset is defined thus:
BookFormset = inlineformset_factory(Author, Book,
fields=('book_id','book_name', 'publisher_name'), extra=1,
can_delete=False)
The template is:
{{ formset.non_form_errors.as_ul }}
<table id="formset" class="form">
{% for form in formset.forms %}
{% if forloop.first %}
<thead><tr>
{% for field in form.visible_fields %}
<th>{{ field.label|capfirst }}
{% endfor %}
</tr></thead>
{% endif %}
<tr class="{% cycle row1,row2 %}">
{% for field in form.visible_fields %}
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% endfor %}
</table>
The fields are displayed column-wise, but I would like them to be displayed row-wise.
The above code produces output like this:
Book name Publisher name
book_field Publisher_field
I would like the output to look like this:
Book name book_field
Publisher name Publisher_field
How can I do this?
In your template, you have two <tr> elements, each of which contains a loop over form.visible_fields, each iteration of which generates a single <th> or <td>.
Change this round so that you have a single loop over form.visible_fields, each iteration of which contains a single <tr> element containing a <th> and a <td>. Like this:
<table id="formset" class="form">
{% for form in formset.forms %}
{% for field in form.visible_fields %}
<tr class="{% cycle row1,row2 %}">
<th>{{ field.label|capfirst }}</th>
<td>
{# Include the hidden fields in the form #}
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
</tr>
{% endfor %}
{% endfor %}
</table>
The examples above seem to show a column-wise layout, which appears to be the default layout when a formset renders itself.
To make it row-wise, use something like this:
<table>
{% for form in formset.forms %}
{% if forloop.first %}
<thead>
{% for field in form.visible_fields %}
<th>{{ field.label }}</th>
{% endfor %}
</thead>
<tbody>
{% endif %}
<tr class="{% cycle row1,row2 %}">
{% for field in form.visible_fields %}
<td>
{% if forloop.first %}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% endif %}
{{ field.errors.as_ul }}
{{ field }}
</td>
{% endfor %}
</tr>
{% if forloop.last %}
</tbody>
{% endif %}
{% endfor %}
</table>

Django - iterate number in for loop of a template

I have the following for loop in my django template displaying days. I wonder, whether it's possible to iterate a number (in the below case i) in a loop. Or do I have to store it in the database and then query it in form of days.day_number?
{% for days in days_list %}
<h2># Day {{ i }} - From {{ days.from_location }} to {{ days.to_location }}</h2>
{% endfor %}
Django provides it. You can use either:
{{ forloop.counter }} index starts at 1.
{{ forloop.counter0 }} index starts at 0.
In template, you can do:
{% for item in item_list %}
{{ forloop.counter }} # starting index 1
{{ forloop.counter0 }} # starting index 0
# do your stuff
{% endfor %}
More info at: for | Built-in template tags and filters | Django documentation
Also one can use this:
{% if forloop.first %}
or
{% if forloop.last %}
{% for days in days_list %}
<h2># Day {{ forloop.counter }} - From {{ days.from_location }} to {{ days.to_location }}</h2>
{% endfor %}
or if you want to start from 0
{% for days in days_list %}
<h2># Day {{ forloop.counter0 }} - From {{ days.from_location }} to {{ days.to_location }}</h2>
{% endfor %}
from the docs https://docs.djangoproject.com/en/stable/ref/templates/builtins/#for
you can found it to count items you can use a counter like this
{% for job in jobs %}
<td>{{ forloop.counter }}</td>
<td>{{ job.title }}</td>
<td>{{ job.job_url }}</td>
{% endfor %}
{{ forloop.counter }} start counting from 1
{{ forloop.counter0 }} start counting from 0
Do like this,
{% for days in days_list %}
<h2># Day {{ forloop.counter }} - From {{ days.from_location }} to {{ days.to_location }}</h2>
{% endfor %}
[Django HTML template doesn't support index as of now], but you can achieve the goal:
If you use Dictionary inside Dictionary in views.py then iteration is possible using key as index. example:
{% for key, value in DictionartResult.items %} <!-- dictionartResult is a dictionary having key value pair-->
<tr align="center">
<td bgcolor="Blue"><a href={{value.ProjectName}}><b>{{value.ProjectName}}</b></a></td>
<td> {{ value.atIndex0 }} </td> <!-- atIndex0 is a key which will have its value , you can treat this key as index to resolve-->
<td> {{ value.atIndex4 }} </td>
<td> {{ value.atIndex2 }} </td>
</tr>
{% endfor %}
Elseif you use List inside dictionary then not only first and last iteration can be controlled, but all index can be controlled. example:
{% for key, value in DictionaryResult.items %}
<tr align="center">
{% for project_data in value %}
{% if forloop.counter <= 13 %} <!-- Here you can control the iteration-->
{% if forloop.first %}
<td bgcolor="Blue"><a href={{project_data}}><b> {{ project_data }} </b></a></td> <!-- it will always refer to project_data[0]-->
{% else %}
<td> {{ project_data }} </td> <!-- it will refer to all items in project_data[] except at index [0]-->
{% endif %}
{% endif %}
{% endfor %}
</tr>
{% endfor %}
End If ;)
//
Hope have covered the solution with Dictionary, List, HTML template, For Loop, Inner loop, If Else.
Django HTML Documentaion for more methods: https://docs.djangoproject.com/en/2.2/ref/templates/builtins/
I think you could call the id, like this
{% for days in days_list %}
<h2># Day {{ days.id }} - From {{ days.from_location }} to {{ days.to_location }}</h2>
{% endfor %}