I have a table Events
, ordered by a field date
.
I want to print out the events in the template, but using a separate div for each date, e.g.:
<div class="content">
<h1>December 30th</h1>
<!-- div for Event 1 from December 30th -->
<!-- div for Event 2 from December 30th -->
</div>
<div class="content">
<h1>December 31st</h1>
<!-- div for Event 1 from December 31st -->
<!-- div for Event 2 from December 31st -->
<!-- div for Event 3 from December 31st -->
</div>
How do I do this?
My current solution is to put the Event objects in a dictionary with the date as the key. This has ordering issues and is inelegant and inefficient.
View:
events = Event.objects.select_related().all()
events_dict={}
for event in events:
date=event.date.strftime('%d %B %Y')
if date in events_dict:
events_dict[date].append(event)
else:
events_dict[date] = [event]
Template:
{% for date, events in events_dict.items %}
<div class="content">
<h1>{{date}}</h1>
{% for event in events %}
{% include "partials/event.html" %}
{% endfor %}
</div>
{% endfor %}
You're looking for the {% regroup %}
tag, which does exactly what you want. It takes a sequence of items (it has to be ordered beforehand, which yours is) and a lookup and groups the sequence by that lookup.
view:
events = Event.objects.select_related.all()
template:
{% regroup events by date as events_by_date %}
{% for date in events_by_date %}
<div class="content">
<h1>{{ date.grouper|date:"d F Y" }}</h1>
{% for event in date.list %}
{% include "partials/event.html" %}
{% endfor %}
</div>
{% endfor %}
(Notice that the date format string is different; the equivalent of %B
in strftime
is F
for the date
filter).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With