在Django中分组日期

时间:2009-08-06 03:45:44

标签: python django django-forms

我的问题与this post几乎完全相同,只是我使用的是Python和Django而不是PHP。

任务是:

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 

输出:

2009-01-01  
1  
2   
2009-01-02  
3  
2009-01-03  
4  
5  

我可以通过循环排序日期并在我的python视图文件中将HTML输出到字符串中来手动破解某些东西,但我想知道:使用Django模板或漂亮的Python功能有更好的方法吗?

5 个答案:

答案 0 :(得分:31)

您可以使用重新组合日期模板标签解决此问题。

{% regroup object_list by start_date|date:"Y-m-d" as objects_by_day %}
{% for d in objects_by_day %}
### DO SOMETHING HERE
{% endfor %}

答案 1 :(得分:15)

itertools.groupby是亲爱的,亲爱的朋友:

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

以上代码打印以下内容:

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')

答案 2 :(得分:9)

对较大数据集itertools.group_by执行报告时可能会太慢。在那些情况下,我让postgres处理分组:

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')

答案 3 :(得分:8)

如果OP可以在模板代码中使用python,这些都是合理的答案。 (在那个帐户上,我赞成使用itertools.groupby()解决方案。)但是你不能在模板代码中使用python。在最好的情况下,您将编写执行此操作的模板标签。并且已经有一个模板标签可以做到这一点。

要在模板中的Django中进行分组,请使用重新组合

{% 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>

示例从Django regroup documentation解除。重新组合至少在django 0.961.01.1中可用。

如果你让我知道传递给模板的内容,我可以破解一个使用你的数据的例子。

此外,还有一个blog post,其中DjangoGrrl可以正好解决这个问题。

答案 4 :(得分:2)

如果您使用数据库的日期格式化功能去除时间(在选择中),这会更容易。然后,您可以按格式化列进行分组(使用列别名)。

之后,您可以使用具有一点逻辑的循环将结果转换为您想要的结果。我还没有使用过django的模板系统,但这是Python中的逻辑:

>>> rows = [(1,'2009-01-01'), (2,'2009-01-01'), (3, '2009-02-02'), \
(4, '2009-02-02'), (5, '2009-02-02')]
>>> topdate = None
>>> for r in rows:
...     if topdate <> r[1]:
...             topdate = r[1]
...             print r[1]
...     print r[0]
... 
2009-01-01
1
2
2009-02-02
3
4
5

应该有一种直接的方式将其转换为django模板代码。