Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grouping dates in Django [duplicate]

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?

like image 551
ine Avatar asked Aug 06 '09 03:08

ine


4 Answers

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 %}
like image 139
Wade Avatar answered Nov 20 '22 07:11

Wade


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')
like image 16
Kenan Banks Avatar answered Nov 20 '22 07:11

Kenan Banks


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')
like image 9
tback Avatar answered Nov 20 '22 06:11

tback


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.

like image 8
hughdbrown Avatar answered Nov 20 '22 08:11

hughdbrown