【问题标题】:How do I tell django to use the PostgreSQL DATE function in Django's .annotate()?如何告诉 django 在 Django 的 .annotate() 中使用 PostgreSQL DATE 函数?
【发布时间】:2020-04-23 09:17:15
【问题描述】:

假设我有模型EventDateTime,它有一个页面外键和一个日期字段。即页面可以有多个不同日期和时间的EventDateTime

模型代码大致如下:

class EventDateTime(Orderable):
    page = ParentalKey("Event", on_delete=models.CASCADE, related_name="dates")
    date = models.DateTimeField(null=False, blank=False)
    # Some other unrelated fields

class Event(Page):
    # Some unrelated fields

该网站的运作方式是,它将在特定时间内向用户显示一定数量的事件(例如 10 个),而忽略同一天发生的多次事件(但不会跨越多天)。基本上这个 SQL 查询:

SELECT page_id, DATE(MIN(date)) 
FROM eventdatetime 
WHERE (date >= '2020-01-05 17:45:48.545123')  
GROUP BY page_id, DATE(date) 
ORDER BY date 
LIMIT 10;

例如可以返回:

 page_id |    date
---------+------------
     296 | 2020-01-07
     301 | 2020-01-07
     298 | 2020-01-09
     289 | 2020-01-10
     266 | 2020-01-11
     267 | 2020-01-11
     268 | 2020-01-11
     269 | 2020-01-11
      54 | 2020-01-13
     290 | 2020-01-13

但是,我无法弄清楚如何将这个确切的意图转换为 Django 的 ORM:

EventDateTime.objects\
    .filter(page__live=True,date__gte=datetime.now())\
    .values('page_id')\
    .annotate(Min('date__date')).order_by('date')

这是返回的 SQL:

SELECT "web_eventdatetime"."page_id", 
    MIN("web_eventdatetime"."date") AS "date__date__min" 
FROM "web_eventdatetime" 
INNER JOIN "web_event" ON ("web_eventdatetime"."page_id" = "web_event"."page_ptr_id") 
INNER JOIN "wagtailcore_page" ON ("web_event"."page_ptr_id" = "wagtailcore_page"."id") 
WHERE ("web_eventdatetime"."date" >= 2020-01-05 18:07:57.516323 AND "wagtailcore_page"."live" = True) 
GROUP BY "web_eventdatetime"."page_id", 
    "web_eventdatetime"."date" <-- does not extract date portion
ORDER BY "web_eventdatetime"."date" ASC

请注意,由于某种原因,Django 在倒数第二行中如何不理解我按DATE(MIN(date)) 而不是MIN(date) 分组的意图(不幸的是,这在这种情况下有所不同)。 :(

我如何告诉 Django 只按日期部分而不是整个日期时间进行分组?

【问题讨论】:

  • 你能显示你的型号代码吗?
  • 这里看起来像date__gte=datetime.now() 你需要date__gte=datetime.now().date()
  • @funnydman 很好 :) 虽然这取决于我是否展示了今天早些时候发生的事件(两种情况都存在)。无论哪种方式,它仍然不会更改查询的 GROUP BY 部分,该部分由 date 而不是 MIN(DATE(date)) 聚合,就像我试图完成的那样

标签: sql django postgresql django-models group-by


【解决方案1】:

使用值表达式中的日期查找显式添加日期字段。这将分组查询集日期字段的日期部分。

 .values('page_id', 'date__date')

【讨论】:

    猜你喜欢
    • 2017-01-15
    • 1970-01-01
    • 2022-06-12
    • 2021-01-30
    • 1970-01-01
    • 2015-01-01
    • 2022-08-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多