Django - 按日期/日期与日期时间字段区分的不同行/对象

时间:2016-10-13 11:36:32

标签: python django postgresql datetime

我现在已经搜索了很长一段时间并且知道了几个问题的答案,但即使我的问题非常简单,也没有一个解决方案在我的最后工作:

我需要什么(使用postgres + django 1.10):我有很多行,在datetime字段中有许多重复日期(=天)。我想要一个包含每个日期/日的一行/对象的查询集。

fk | col1 | colX | created (type: datetime)
----------------------------------------------
1  | info | info | 2016-09-03 08:25:52.142617+00:00 <- get it (time does not matter)
1  | info | info | 2016-09-03 16:26:52.142617+00:00
2  | info | info | 2016-09-03 11:25:52.142617+00:00
1  | info | info | 2016-09-14 16:26:52.142617+00:00 <- get it (time does not matter)
3  | info | info | 2016-09-14 11:25:52.142617+00:00
1  | info | info | 2016-09-25 23:25:52.142617+00:00 <- get it (time does not matter)
1  | info | info | 2016-09-25 16:26:52.142617+00:00
1  | info | info | 2016-09-25 11:25:52.142617+00:00
2  | info | info | 2016-09-25 14:27:52.142617+00:00
2  | info | info | 2016-09-25 16:26:52.142617+00:00
3  | info | info | 2016-09-25 11:25:52.142617+00:00
etc.

这是最好的(性能+ pythionic / django)方式。我的模型/表格将有很多行(>百万)。

编辑1

必须先用fk(例如WHERE fk = 1)过滤结果。

我已经尝试过最明显的事情,比如

MyModel.objects.filter(fk=1).order_by('created__date').di‌​stinct('created__dat‌​e') 

但出现以下错误:

  

django.core.exceptions.FieldError:无法解析关键字&#39; date&#39;进入田野。加入&#39;创建&#39;不允许。

...与all()的相同错误以及通过类Meta而不是query-method order_by()的相应排序......

在这种特定情况下,有人可能会更多地了解这个错误吗?

2 个答案:

答案 0 :(得分:1)

在当前的Django实现中似乎不可能,因为这将涉及使用高级DB后端函数(如Postgres window functions)。

你最接近的是使用聚合:

MyModel.objects.annotate(
    created_date=TruncDay('created')
).values('created_date').annotate(id=Min('id'))

这将聚合相似的日期,并获取最小ID。

[{'created_date': datetime.date(2017, 3, 16), 'id': 146},
 {'created_date': datetime.date(2017, 3, 28), 'id': 188},
 {'created_date': datetime.date(2017, 3, 24), 'id': 178},
 {'created_date': datetime.date(2017, 3, 23), 'id': 171},
 {'created_date': datetime.date(2017, 3, 22), 'id': 157}] ...

如果您需要整个对象,可以使用.values_list()和另一个查询集进行链接,这将产生一个子查询:

MyModel.objects.filter(
    id__in=MyModel.objects.annotate(
        created_date=TruncDay('created')
    ).values('created_date').annotate(id=Min('id')).values_list(
        'id', flat=True
    )
)

仅供参考,这导致以下查询

SELECT
    "myapp_mymodel"."id",
    "myapp_mymodel"."created",
    "myapp_mymodel"."col1",
    "myapp_mymodel"."colX"
FROM "myapp_mymodel"
WHERE "myapp_mymodel"."id" IN (
    SELECT MIN(U0."id") AS "id"
    FROM "myapp_mymodel" U0
    GROUP BY DATE(U0."created")
)

答案 1 :(得分:-2)

您可以使用Queryset通过创建值的不同来获取表中的结果,因为您使用的是postgresql。

也许像这样的查询应该做的工作:

MyModel.objects.all().distinct('created__date')

我也引用了django的查询集文档:https://docs.djangoproject.com/fr/1.10/ref/models/querysets/#distinct