Django 2 - Как выполнить запрос к нескольким значениям полей не из БД - PullRequest
0 голосов
/ 10 мая 2019

У меня трудные времена, чтобы найти какой-нибудь умный и надежный способ запуска нескольких аннотаций для каждой указанной даты и времени, которые я предоставляю в начале запроса, и которые не хранятся в базе данных, поскольку рассчитываются на лету.

Мои данные

from datetime import datetime

business_dates = [
    datetime(year=2016, month=1, day=5),
    datetime(year=2016, month=1, day=6),
    datetime(year=2016, month=1, day=7),
]

Мои модели:

class Employee(models.Model):
    name = models.CharField(max_length=100, default='Not specified')
    created = models.DateTimeField(auto_now_add=True)

Желаемый выход

Имейте в виду, total_employee_count должно отображать общее количество сотрудников на указанную дату. Упомянутые данные могут быть не такими последовательными, как показывает пример данных.

[
    {'date': datetime(year=2016, month=1, day=5), 'total_employee_count': 22},
    {'date': datetime(year=2016, month=1, day=6), 'total_employee_count': 24},
    {'date': datetime(year=2016, month=1, day=7), 'total_employee_count': 29},
]

Чего я не хочу:

Цикл business_dates и выполнение одного отдельного запроса для каждой даты. В случае 100 дат я не хочу запускать 100 отдельных запросов. Допустим, сейчас работает подзапрос.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 10 мая 2019

Это решит вашу проблему:

from django.db.models import Count
...
Employee.objects.filter(
  created__in=business_dates
).values(
    'created'
).annotate(
    employee_count=Count('pk')
)

Здесь мы делаем группировку по дате (при фильтрации по требуемому списку), а затем подсчитываем количество объектов за дату.

1 голос
/ 10 мая 2019
from django.db.models import Count, DateTimeField
from django.db.models.functions import Trunc
from django.contrib.auth.models import User


business_dates = [
    datetime.datetime(year=2016, month=1, day=5),
    datetime.datetime(year=2016, month=1, day=6),
    datetime.datetime(year=2016, month=1, day=7),
]


ret = (
    Employee.objects
    .annotate(day=Trunc('created', 'day', output_field=DateTimeField()))
    .filter(day__in=business_dates)
    .values('day')
    .annotate(count=Count('id'))
    .values('day', 'count')
)
...