2009-08-06 86 views
13

我的问题几乎和this post一样,除了我使用Python和Django而不是PHP。在Django中分组日期

的任务是采取:

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 

我可以手动通过排序日期循环和输出HTML成字符串在我的Python查看文件砍东西一起,但我想知道:是否有更好的方式使用Django模板或漂亮的Python功能?

回答

30

您可以通过重组日期 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 %} 
+0

我是那里的大部分,但没有意识到你可以混合使用日期过滤器。非常感谢!正是我在找什么。 – saturdayplace 2010-04-16 22:26:29

+0

好神,怎么没我知道这个 – 2012-01-26 10:36:33

+0

它的速度更快,如果你需要“日期部分” – 2014-01-06 18:47:56

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的模板代码直接的方式。

+0

我可以将数据分组,但模板系统内部的“小逻辑”是什么样子? – ine 2009-08-06 04:18:07

+0

我添加了一个例子。 – 2009-08-06 05:06:18

+0

我不相信你可以在Django模板中做到这一点。即使你可以,你也不想。最好这样做: (1)视图代码或(2)可以使用真正的Python的模板标签。 – hughdbrown 2009-08-06 17:14:29

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

非常好! itertools.groupby就是我正在寻找的。 – ine 2009-08-06 18:08:25

+0

如果您打算在视图中执行此操作,您需要如下所示: “ite sidebar_date_list(): from itertools import group by data = [datetime.date(post.created_at.year,post.created_at.month ,1)Post.objects.filter(publish = 1).order_by(' - created_at')] return {'months':[k for k,_ in groupby(data)]} 请注意, SQL必须被排序以供groupby()使用。“从这里解除: http://www.djangrrl.com/view/using-python-str-datetime-lists-and-sets-to-group-dates/ – hughdbrown 2009-08-06 18:17:42

+0

或者像这样,如果你想按天分组:“ def sidebar_date_list(): \t from itertools import groupby \t data = [datetime.date(post.created_at.year,post.created_at.month,post.created_at.day)for post in Post.objects.filter(publish = 1) ).order_by( ' - created_at')] \t回{ '天':[K为K,_在GROUPBY(数据)]}” – hughdbrown 2009-08-06 18:19:47

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解除。 regroup至少可在django 0.961.01.1中找到。

如果你给了我一个关于传递给模板的信息,我可以用一个使用你的数据的例子来破解它。

另外,还有一个blog post其中DjangoGrrl完全通过这个问题。

+0

模板语言倾向于提供足够的相同语言结构,您可以轻松地在两者之间进行转换(它们共享相同的目标字节码)。 – 2009-08-06 17:40:40

+0

不要粗鲁,但是你在Django中编程吗?实际上,只有基本的比较和分配操作。看看什么是可用的,而无需使用templatetags: http://docs.djangoproject.com/en/dev/topics/templates/ – hughdbrown 2009-08-06 18:03:51

+0

不幸的是,我使用的是0.96,但是这是为那些对1.0或更高的很好的资源! – ine 2009-08-06 18:06:33

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