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

Sch*_*itz 6 python django postgresql datetime

我已经搜索了很长时间,并且知道关于 sof 的几个答案,但是即使我的问题非常简单,但没有一个解决方案在我结束时有效:

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

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.
Run Code Online (Sandbox Code Playgroud)

什么是最好的(性能 + pythionic/django)方式来做到这一点。我的模型/表将有很多行(> 百万)。

编辑 1

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

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

MyModel.objects.filter(fk=1).order_by('created__date').di??stinct('created__dat??e') 
Run Code Online (Sandbox Code Playgroud)

但出现以下错误:

django.core.exceptions.FieldError:无法将关键字“日期”解析为字段。不允许在“创建”时加入。

...与 all() 和通过类 Meta 进行相应排序而不是查询方法 order_by() 的相同错误...

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

Ant*_*wan 8

考虑到当前的 Django 实现,这似乎是不可能的,因为这将涉及使用高级数据库后端函数(如Postgres 窗口函数)。

您所拥有的最接近的是使用聚合:

MyModel.objects.annotate(
    created_date=TruncDay('created')
).values('created_date').annotate(id=Min('id'))
Run Code Online (Sandbox Code Playgroud)

这将聚合相似的日期,并选取最小的 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}] ...
Run Code Online (Sandbox Code Playgroud)

如果您需要整个对象,您可以将其与一个.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
    )
)
Run Code Online (Sandbox Code Playgroud)

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

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")
)
Run Code Online (Sandbox Code Playgroud)


Mat*_*Dfr -2

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

也许像这样的查询应该可以完成工作:

MyModel.objects.all().distinct('created__date')
Run Code Online (Sandbox Code Playgroud)

我也向您推荐 django 的查询集文档:https://docs.djangoproject.com/fr/1.10/ref/models/querysets/#distinct

  • `MyModel.objects.filter(xyz=123).order_by('created__date').distinct('created__date')` _django.core.exceptions.FieldError:无法将关键字“date”解析为字段。不允许加入“创建”。_ (2认同)