How can I display a table in a template with additional category/section rows?
Have a nice day!
I have a non-standard table. Which I plan to display in the template.
I load the table into the template from the model. And I have additional sections - additional fields. These additional fields characterize - Category, Section, Topics. I am thinking how to display such a table from the model in the template - as shown in the picture.
To additionally implement additional fields - categories or sections in the table.
I have a rough idea -
I have to create a transit model for exactly such a table - in which the number of rows is equal to the number of rows of the original table + plus the number of rows of category sections in addition. That is, there can be about 25 rows of the original table and + plus 6 rows - category sections. In total, the required table will have 31 rows of rows.
But how to display them in the form as in my picture - separating categories sections?
models.py
class CreateNewGPR (models.Model):
name_object = models.IntegerField(verbose_name="")
name_category = models.CharField(verbose_name="")
name_working = models.CharField(verbose_name="")
type_izm = models.CharField(choices=TYPE_IZMERENIYA, verbose_name="")
value_work = models.FloatField(verbose_name="")
lyudi_norma = models.IntegerField(verbose_name="")
technik_norma = models.IntegerField(verbose_name="")
date_begin = models.DateField(verbose_name="")
date_end = models.DateField(verbose_name="")
views.py
filter_qs = CreateNewGPR.objects.filter(name_object=pk) filter_qs = filter_qs.values("name_working", "type_izm", "value_work", "lyudi_norma", "technik_norma", "date_begin", "date_end")
context['books'] = filter_qs
template.html
<div>
<table class="pure-table">
<thead>
<tr>
<th>Name Column 1</th>
<th>Name Column 2</th>
<th>Name Column 3</th>
<th>Name Column 4</th>
<th>Name Column 5</th>
<th>Name Column 6</th>
<th>Name Column 7</th>
</tr>
</thead>
<tbody>
{% for book in books %}
<tr>
<td>{{ book.name_working }}</td>
<td>{{ book.type_izm }}</td>
<td>{{ book.value_work }}</td>
<td>{{ book.lyudi_norma }}</td>
<td>{{ book.technik_norma }}</td>
<td>{{ book.date_begin }}</td>
<td>{{ book.date_end }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
Just associate it in your code if you are sure that there will always only one page with few objects:
def get_context_data(self, **kwargs) -> dict[str, typing.Any]:
context = super().get_context_data()
categories = collections.defaultdict(list)
for object in self.get_queryset():
categories[object.category].append(object)
context["categories"] = categories
return context
And then render it in template (here is example of html, fill it in template by yourself):
<table>
<thead>
<tr>
<th>col1</th>
<th>col2</th>
<th>col3</th>
</tr>
</thead>
<tbody>
<tr>
<th colspan="3">category 1</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<th colspan="3">category 2</th>
</tr>
<tr>
<td>1</td>
<td>2</td>
<td>2</td>
</tr>
</tbody>
</table>
🧩 1. Update views.py
to group data by category
python
CopyEdit
from collections import defaultdict
def your_view(request, pk):
# Get all objects for a specific `name_object`
filter_qs = CreateNewGPR.objects.filter(name_object=pk)
# Group by category
grouped_data = defaultdict(list)
for item in filter_qs:
grouped_data[item.name_category].append(item)
context = {
'grouped_data': grouped_data.items() # returns list of (category, items)
}
return render(request, 'your_template.html', context)
🖼️ 2. Update your template.html
to display grouped sections
html
CopyEdit
<table class="pure-table">
<thead>
<tr>
<th>Name Working</th>
<th>Type</th>
<th>Value</th>
<th>Lyudi Norma</th>
<th>Technik Norma</th>
<th>Start Date</th>
<th>End Date</th>
</tr>
</thead>
<tbody>
{% for category, items in grouped_data %}
<!-- Category Row -->
<tr style="background-color:#f0f0f0; font-weight:bold;">
<td colspan="7">Category: {{ category }}</td>
</tr>
{% for item in items %}
<tr>
<td>{{ item.name_working }}</td>
<td>{{ item.type_izm }}</td>
<td>{{ item.value_work }}</td>
<td>{{ item.lyudi_norma }}</td>
<td>{{ item.technik_norma }}</td>
<td>{{ item.date_begin }}</td>
<td>{{ item.date_end }}</td>
</tr>
{% endfor %}
{% endfor %}
</tbody>
</table>
This will render your table grouped by name_category
, with clear section headers inserted dynamically — no need to manually create a “transit” model or add extra rows.
🔁 Bonus: Sorting by name_category
If you want sections to appear in a specific order:
filter_qs = CreateNewGPR.objects.filter(name_object=pk).order_by('name_category', 'name_working')