Reputation: 4316
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!
Upvotes: 1
Views: 7373
Reputation: 66
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 %}
Upvotes: 0
Reputation: 788
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>
Upvotes: 2
Reputation: 118438
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 %}
Upvotes: 8
Reputation: 4287
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.
Upvotes: 1
Reputation: 3252
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>
Upvotes: 2