Как я могу сказать django использовать функцию PostgreSQL DATE в Django .annotate ()? - PullRequest
0 голосов
/ 05 января 2020

Предположим, у меня есть модель 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 сгруппировать только по части даты, а не по всей дате?

1 Ответ

0 голосов
/ 05 января 2020

Добавьте явно поле даты с поиском даты в выражении значений. Это сгруппирует в части даты поля даты набора запросов.

 .values('page_id', 'date__date')
...