Django/Python: Loop over selected form fields in Django template - django

I have a form with n fields. The first 4 fields should be displayed differently in my template then the rest of the form. Therefore, I was wondering if I can somehow loop over the first 4 fields, end the loop and continue looping over the rest of the fields later in the template.
<table>
{% for field in form %}
{% if forloop.counter == 4 <<< Break here >>>%}
<tr>
<td> {{ field.label_tag }} </td>
<td> {{ field }} </td>
</tr>
{% endfor %}
</table>
.... Different code ....
<table>
{% for field in form %} <<< Continue here >>>
<tr>
<td> {{ field.label_tag }} </td>
<td> {{ field }} </td>
</tr>
{% endfor %}
</table>
I have found this code but I was wondering if I could structure the template differently or if I have missed some new changes in Django 1.3 which allow the breaking of loops now.
Normally, I would split the form in two seperate forms, but I would like to reuse the form definition in other templates as well, therefore I would like to keep all information together in one form.
Thank you for your advice!

It's the same solution as other "can't do it in the template" problems: do it in the view. I truly believe added complexity and further separation of logic into multiple code areas (tags, new files, etc.) only hurts maintainability. I separate / implement DRY only when things actually do get repetitive, unreadable, etc.
Everything else is premature optimization.
Django won't know the difference when a form is submitted.
fields = list(form)
part1, part2 = fields[:4], fields[4:]
{% for field in part1 %}{{ field }}{% endfor %}
...
{% for field in part2 %}{{ field }}{% endfor %}

I would suggest you write your own custom template. Perhaps your filter could look like this:
def show_part(form,section=1):
display = ''
for id,field in enumerate(form):
if int(section) == 1 and id > 3:
break
elif int(section) == 2 and id < 3:
continue
display += '<tr><td>'+field.label_tag+'</td>'
display += '<td>'+field+'</td></tr>'
return display
and use the following in your template:
<table>
{{ form|show_part:"1" }}
</table>
<table>
{{ form|show_part:"2" }}
</table>

Since form is a list, you could also use Django's built-in slice template filter: https://docs.djangoproject.com/en/1.3/ref/templates/builtins/#slice
Your example would become:
<table>
{% for field in form|slice:":4" %}
<tr>
<td> {{ field.label_tag }} </td>
<td> {{ field }} </td>
</tr>
{% endfor %}
</table>
.... Different code ....
<table>
{% for field in form|slice:"4:" %}
<tr>
<td> {{ field.label_tag }} </td>
<td> {{ field }} </td>
</tr>
{% endfor %}
</table>

You're almost there, if you just add
<table>
{% if forloop.counter <= 4 %}
... first four fields
{% else %}
... other fields
{% endif %}
If you need two different tables you could add:
{% if forloop.counter == 1 %}
<table>
{% endif %}
{% if forloop.last %}
</table>
{% endif %}
That's not a very pretty solution, but it works. You could also consider using two forms.

Shorter than "Yuji 'Tomita' Tomita" answer
Make list for form on your view:
context = {'form': list(form)}
return render(request, template, context)
and get each field on template by |slice
{% for field in form|slice:":4" %}
<tr>
<td> {{ field.label_tag }} </td>
<td> {{ field }} </td>
</tr>
{% endfor %}

Related

Django template tags - arrange result of queryset

I am trying to format my results in a table.
<tr>
<td>A6</td>
<td>A6 title</td>
<td>
{% for record in a6titles %}
titles: {{ record }}
{% endfor %}
</td>
</tr>
The data displays in a single row. I would like each result item to be displayed in its own row. I am sure this is very simple; however, I am very new to this.
# You need to put your tr tag in for loop
{% for record in a6titles %}
<tr>
<td>A6</td>
<td>A6 title</td>
<td>titles: {{ record }}</td>
</tr>
{% endfor %}

How to loop through crispy fields

How can I arrange my form in a table?
I had a normal form and I was arranging it in my template like this.
<table border="0" >
{% for field in form %}
<tr >
<td>
<label for="{{ field.label }}">{{ field.label_tag }}
{% if field.field.required %}<span style="color:red"; class="special_class">*</span>{% endif %}</label>
</td>
<td>
{{ field }}
</td>
</tr>
{% endfor %}
</table>
Now I want to use crispy forms. but couldn't figure out how to display my form.
of cause it has works with this.
{% load crispy_forms_tags %}
{% crispy form %}
but that was not arranging my fields well,
how can I access these fields by a loop?
Any help would be greatly appreciated.
You can iterate over fields and then use crispy like this:
{% for field in form %}
{{ field|as_crispy_field }}
{% endfor %}

Django Template loop with variable

I am having issue with django html variable so I made the below code which is working .
{%for field in instance %}
<tr>
<td width="250">
{{ field.Item }}
</td>
<td>
<input type="text" value={{ field.P_640 }} >
</td>
{% endfor %}
But at the view section I have variables and sometimes I am pushing filter value. P_640 and sometimes P_630 .How can I make my template to look to the colomn 1 instead of looking the field name like {{ field.P_640 }} , because it's not working when I push P_630. ?
This is how you would do it:
{% for field in instance %}
<tr>
<td width="250">
{{ field.Item }}
</td>
<td>
<input type="text" value="
{% if field.P_640 }}
{{ field.P_640 }}
{% elif field.P_630 %}
{{ field.P_630 }}
{% endif %}
">
</td>
</tr>
{% endfor %}
Check for every value that could exist and then output it.
If there are multiple values, replace {% elif %} with {% endif %} {% if %};

cant get an id to be added to a django formset

im getting an error when trying to POST a form, which doesn't make much sense.
the error:
MultiValueDictKeyError at /admin/courses/course-selector/add/
"Key 'form-0-id' not found in <QueryDict:
so i've done the googling and worked out that because i'm drawing the form myself (I'd built a table and printed out each field in the place i wanted it).
so I've tried to add in a field with the id and it doesn't print. it just doesn't have an id in the template for me to write into the form. im not sure what to do now cos the established advice for this case in google i've followed and found an issue.
the template code.
<form action="." method="POST" id="formset">
<table>
<tr>
{{ formset.management_form }}
</tr>
<tr>
<th></th>
{% for field in formset.forms.0 %}
{% if not field.is_hidden %}
<th>{{ field.label }}</th>
{% endif %}
{% endfor %}
</tr>
{% for f in formset.forms %}
<tr>
<td><input type="checkbox" id="checkbox_{{ f.id }}" /></td>
<td>{{ f.id }}</td>
{% for field in f %}
{% if not field.is_hidden %}
<td>
{{ field.errors }}
{{ field }}
</td>
{% else %}
<td valign="bottom">{{ field }}</
{% endif %}
{% endfor %}
</tr>
{% endfor %}
</table>
</form>
snipped for brevity...
why doesn't {{ f.id }} output anything.
edit1
adding in the code that generates the formset, it might be why im not getting an id.
InstanceFormSet = formset_factory(BulkAddInstanceForm, extra=0)
# build the list for populating the forms
n, datalist = 0, []
while n < int(input_data['copies']):
datalist.append(data)
n +=1
formset = InstanceFormSet(initial=datalist)
i've found multiple errors in your template:
you are iterating over all forms in the formset but you are also displaying all non hidden fields of the first form. this means you have duplicated fields
later you are iterating over all fields in all forms. but you are also displaying the id field twice. once as a field and one as part of the checkbox id. if the form doesn't have an id field it does not output anything as f.id
I use {{forloop.counter0}} or {{forloop.counter}}
to work out what the id for the form in the formset should be
A few years late to the game, but this is the answer. Put this under {% for f in formset.forms %}
{{ forloop.counter }}
This will output the number associated with each form (eg. 1, 2, 3, etc.)

Django: display text between form fields

Hi Stackoverflow people,
I am displaying a large form through a loop:
<table>
{% for field in projectDetailForm %}
<tr>
<td> {{ field.label_tag }} </td>
<td> {{ field }} </td>
</tr>
{% endfor %}
</table>
I would like to interrupt the table with the form fields after a few form fields to display more explanations. Since the form is fairly large (20 fields), I would like to avoid the "manual display" of each form field (as described here).
Is there a way to display the text form within the loop, either after the x-th loop or after a specific form field?
Thank you for your advice!
I would either use forloop.counter or set a custom attribute on a form field on form initialization and display the attribute the same way you display field.label_tag
You can add a method to your form, which will return fields by portions. Something like:
def by_5(self):
iterable = iter(self)
zipped = zip(*([iterable] * 5)) # replace 5 by desired n
for z in zipped:
yield z
remained = list(iterable)
if remained:
yield remained
Then in template:
<table>
{% for fields in projectDetailForm.by_5 %}
{% for field in fields %}
<tr>
<td> {{ field.label_tag }} </td>
<td> {{ field }} </td>
</tr>
{% endfor %}
<tr><td colspan="2">Hi there!</td></tr>
{% endfor %}
</table>
There is a {{ forloop.counter }} and {{ forloop.counter0 }} (1-indexed and 0-indexed respectively) that you can use.
For a few more information, check this Djangobook link.