My question is almost exactly the same as this post, except that I'm using Python and Django instead of PHP.
The task is to take:
id date
1 2009-01-01 10:15:23
2 2009-01-01 13:21:29
3 2009-01-02 01:03:13
4 2009-01-03 12:20:19
5 2009-01-03 13:01:06
And output:
2009-01-01
1
2
2009-01-02
3
2009-01-03
4
5
I can manually hack something together by looping through the sorted dates and outputting HTML into a string in my python view file, but I'm wondering: is there's a better way using a Django template or a nifty Python feature?
You can solve this with the regroup and date templatetags.
{% regroup object_list by start_date|date:"Y-m-d" as objects_by_day %}
{% for d in objects_by_day %}
### DO SOMETHING HERE
{% endfor %}
itertools.groupby
is your dear, dear friend:
import itertools
dates = [
(1,'2009-01-01 10:15:23'),
(2,'2009-01-01 13:21:29'),
(3,'2009-01-02 01:03:13'),
(4,'2009-01-03 12:20:19'),
(5,'2009-01-03 13:01:06'),
]
for key,group in itertools.groupby(dates, key=lambda x: x[1][:11]):
print key
for element in group:
print ' ', element
The above code prints the following:
2009-01-01
(1, '2009-01-01 10:15:23')
(2, '2009-01-01 13:21:29')
2009-01-02
(3, '2009-01-02 01:03:13')
2009-01-03
(4, '2009-01-03 12:20:19')
(5, '2009-01-03 13:01:06')
When doing reports on larger datasets itertools.group_by
might be too slow. In those cases I make postgres handle the grouping:
truncate_date = connection.ops.date_trunc_sql('day','timestamp')
qs = qs.extra({'date':truncate_date})
return qs.values('date').annotate(Sum('amount')).order_by('date')
These are all reasonable answers if the OP could use python in the template code. (And on that account, I would favor the itertools.groupby() solution.) But you can't use python in template code. In the best case, you'd write a templatetag that performed this operation. And there is already a templatetag that does this.
To do the grouping in Django inside the template, use regroup:
{% regroup people by gender as gender_list %}
<ul>
{% for gender in gender_list %}
<li>{{ gender.grouper }}
<ul>
{% for item in gender.list %}
<li>{{ item.first_name }} {{ item.last_name }}</li>
{% endfor %}
</ul>
</li>
{% endfor %}
</ul>
Example lifted from Django regroup documentation. regroup is available in django 0.96, 1.0, and 1.1, at least.
If you gave me an idea of what is passed through to the template, I could hack up an example that uses your data.
Also, there is a blog post in which DjangoGrrl works through exactly this question.
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