How to render form.as_table in multiple columns
Question:
I am using a model form, and I have rendering that form in the template as below.
<table>
{{form.as_table}}
</table>
But the problem is, its rendering all the fields as rows. Since my model contains more than 200 rows,
when its showing the elements as 200 rows its looking bad. I want to divide them into 5 columns, so the
total rows will be around 40-43. Is there any inbuilt template tag available for this or any other way using which we can solve the problem.
Answers:
You can refer this doc: looping over form fields
What you can do in your template is
{% for field in form %}
{%if forloop.counter|divisibleby:"5" %}
{#after 5 fields, somehow put elements in next row
of table, paragraph, or using divs etc
#}
{%endif%}
{{field}}
{%endfor%}
Your question is a bit unclear however this example is more than enough.
the loop iterates over a list data
and I have replaced so that it would display column1,column2,column3,column4,column5
in every row for example purposes.
<!DOCTYPE html>
<html>
<head>
<title>Jack of All Trades</title>
</head>
<body>
<table border="1">
{% for element in data %}
<tr>
<td><p>column 1 </p></td>
<td><p>column 2 </p></td>
<td><p>column 3 </p></td>
<td><p>column 4 </p></td>
<td><p>column 5 </p></td>
</tr>
{% endfor %}
</tr>
</table>
</body>
</html>
Assuming data
has 5 elements it would produce something like this:
This worked better for me (divisibleby: n, n = number of columns):
<form enctype="multipart/form-data" method="POST">
{% csrf_token %}
{% for field in form %}
{{ field.label }} {{ field }}
{% if forloop.counter|divisibleby:"2" %}
<br>
{% endif %}
{% endfor %}
<input type="submit" value="Continue" />
</form>
I use bootstrap 4 and form tag name is ’employee_in’. There is 6 input fields in each of the two columns (fixed, anyone else knows how to make it automatic?) best I can do so far, hope it helps
<form enctype="multipart/form-data" method="post">
{% csrf_token %}
<div class="container-fluid">
<div class="row">
<div class="col-lg-6">
<table class = 'table table-hover'>
{% for my_divider in employee_in %}
{% if forloop.counter <= 6 %}
<tr>
<td>{{ my_divider.label }}</td>
<td>{{ my_divider }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
</div>
<div class="col-lg-6">
<table class = 'table table-hover'>
{% for my_divider in employee_in %}
{% if forloop.counter > 6 %}
<tr>
<td>{{ my_divider.label }}</td>
<td>{{my_divider}}</td>
</tr>
{% endif %}
{% endfor %}
</table>
</div>
</div>
<input type="submit" class = 'btn btn-secondary' value="Submit">
</div>
</form>
<form method="POST">
{% csrf_token %}
<table>
{% for field in form %}
<tr>
<td>{{ field.label}}</td>
<td>{{ field }}</td>
</tr>
{% endfor %}
</table>
<button type="submit" class="btn btn-primary">Submit</button>
Another option to consider in newer versions of Django is to use Reusable form templates to create a form template to call as {{ form.as_td }}
, just like you would call {{ form.as_table }}
in your template.
This has a few nice features:
- A
FormSet
with each form wrapped in a <tr>
but fields wrapped in <td>
can coexist with other nice add-ons like django-dynamic-formset
- This method can be used for other elements your might want to render forms with
Steps:
- Create a
RenderMixin
that implements as as_td()
method, to be called as {{ form.as_td }}
in your template
from django.forms.utils import RenderableMixin
class ColumnRenderableFormMixin(RenderableMixin):
def as_td(self):
"""Render as <td> elements excluding the surrounding <table> tag."""
return self.render(self.template_name_td)
- Create a reusable template in your app templates directory (or other suitable directory)
- The template will look just like the standard Django templates in django/forms/templates/django/forms/*.html
- A bare bones example put into
someapp/templates/td.html
could be:
{% for field, errors in fields %}
<td>
{{ errors }}
{{ field }}
</td>
{% endfor %}
- Add the custom mixin to your form, and specify the
td.html
template file path in the template_name_td
class variable:
class SomeForm(ModelForm, ColumnRenderableFormMixin):
template_name_td = "someapp/td.html"
- In your view’s template, render the form with
{{ form.as_td }}
.
- If you’re using a formset this would look like the following:
<table class="table">
{% for form in formset %}
<tr>
{{ form.as_td }}
</tr>
{% endfor %}
</table>
I am using a model form, and I have rendering that form in the template as below.
<table>
{{form.as_table}}
</table>
But the problem is, its rendering all the fields as rows. Since my model contains more than 200 rows,
when its showing the elements as 200 rows its looking bad. I want to divide them into 5 columns, so the
total rows will be around 40-43. Is there any inbuilt template tag available for this or any other way using which we can solve the problem.
You can refer this doc: looping over form fields
What you can do in your template is
{% for field in form %}
{%if forloop.counter|divisibleby:"5" %}
{#after 5 fields, somehow put elements in next row
of table, paragraph, or using divs etc
#}
{%endif%}
{{field}}
{%endfor%}
Your question is a bit unclear however this example is more than enough.
the loop iterates over a list data
and I have replaced so that it would display column1,column2,column3,column4,column5
in every row for example purposes.
<!DOCTYPE html>
<html>
<head>
<title>Jack of All Trades</title>
</head>
<body>
<table border="1">
{% for element in data %}
<tr>
<td><p>column 1 </p></td>
<td><p>column 2 </p></td>
<td><p>column 3 </p></td>
<td><p>column 4 </p></td>
<td><p>column 5 </p></td>
</tr>
{% endfor %}
</tr>
</table>
</body>
</html>
Assuming data
has 5 elements it would produce something like this:
This worked better for me (divisibleby: n, n = number of columns):
<form enctype="multipart/form-data" method="POST">
{% csrf_token %}
{% for field in form %}
{{ field.label }} {{ field }}
{% if forloop.counter|divisibleby:"2" %}
<br>
{% endif %}
{% endfor %}
<input type="submit" value="Continue" />
</form>
I use bootstrap 4 and form tag name is ’employee_in’. There is 6 input fields in each of the two columns (fixed, anyone else knows how to make it automatic?) best I can do so far, hope it helps
<form enctype="multipart/form-data" method="post">
{% csrf_token %}
<div class="container-fluid">
<div class="row">
<div class="col-lg-6">
<table class = 'table table-hover'>
{% for my_divider in employee_in %}
{% if forloop.counter <= 6 %}
<tr>
<td>{{ my_divider.label }}</td>
<td>{{ my_divider }}</td>
</tr>
{% endif %}
{% endfor %}
</table>
</div>
<div class="col-lg-6">
<table class = 'table table-hover'>
{% for my_divider in employee_in %}
{% if forloop.counter > 6 %}
<tr>
<td>{{ my_divider.label }}</td>
<td>{{my_divider}}</td>
</tr>
{% endif %}
{% endfor %}
</table>
</div>
</div>
<input type="submit" class = 'btn btn-secondary' value="Submit">
</div>
</form>
<form method="POST">
{% csrf_token %}
<table>
{% for field in form %}
<tr>
<td>{{ field.label}}</td>
<td>{{ field }}</td>
</tr>
{% endfor %}
</table>
<button type="submit" class="btn btn-primary">Submit</button>
Another option to consider in newer versions of Django is to use Reusable form templates to create a form template to call as {{ form.as_td }}
, just like you would call {{ form.as_table }}
in your template.
This has a few nice features:
- A
FormSet
with each form wrapped in a<tr>
but fields wrapped in<td>
can coexist with other nice add-ons like django-dynamic-formset - This method can be used for other elements your might want to render forms with
Steps:
- Create a
RenderMixin
that implements asas_td()
method, to be called as{{ form.as_td }}
in your template
from django.forms.utils import RenderableMixin
class ColumnRenderableFormMixin(RenderableMixin):
def as_td(self):
"""Render as <td> elements excluding the surrounding <table> tag."""
return self.render(self.template_name_td)
- Create a reusable template in your app templates directory (or other suitable directory)
- The template will look just like the standard Django templates in django/forms/templates/django/forms/*.html
- A bare bones example put into
someapp/templates/td.html
could be:
{% for field, errors in fields %}
<td>
{{ errors }}
{{ field }}
</td>
{% endfor %}
- Add the custom mixin to your form, and specify the
td.html
template file path in thetemplate_name_td
class variable:
class SomeForm(ModelForm, ColumnRenderableFormMixin):
template_name_td = "someapp/td.html"
- In your view’s template, render the form with
{{ form.as_td }}
.
- If you’re using a formset this would look like the following:
<table class="table">
{% for form in formset %}
<tr>
{{ form.as_td }}
</tr>
{% endfor %}
</table>