Django наборов запросов. Аннотируйте разные поля одним запросом - PullRequest
1 голос
/ 02 марта 2020

Я написал 3 запроса в базу данных, чтобы получить разные значения. Мне нужно объединить эти запросы в один запрос.

    # Counting Total Number of Plans by Day
    Day.objects.annotate(num_of_plans=Count('plan')) \
        .values('num_of_plans', 'date', 'id')

    # Counting is_completed=True Plans by Day
             Day.objects \
            .filter(plan__is_completed=True) \
            .annotate(num_of_completed_plans=Count('plan__is_completed')) \
            .values('num_of_completed_plans', 'id', 'date')


     # Counting status=deferred Plans by Day
       Day.objects \
            .filter(plan__status='deferred') \
            .annotate(num_of_deferred_plans=Count('plan__is_completed')) \
            .values('num_of_deferred_plans', 'id', 'date')

Как вы можете видеть выше, есть 3 запроса. Каким-то образом мне нужно оптимизировать этот код и получить значения с помощью одного запроса

моделей

class Day(models.Model):
    date = models.DateField(default=datetime.date.today, unique=True)

class Plan(models.Model):
    title = models.CharField(max_length=255)
    status = models.CharField(max_length=255, choices=PLAN_STATUSES, null=True, default='upcoming')
    is_completed = models.BooleanField(default=False, null=True)

    day = models.ForeignKey(Day, CASCADE, null=True)

Есть ли способы оптимизировать эти 3 запроса и получить значения с одним запросом?

1 Ответ

1 голос
/ 02 марта 2020

Поскольку , вы можете использовать параметр filter=… [Django -doc] в выражении Count. Что касается фильтрации на Bool, вы можете просто использовать выражение Sum [Django -doc] :

from django.db.models import Count, Q, Sum

Day.objects.annotate(
    num_of_plans=Count('plan'),
    num_of_completed_plans=<b>Sum('plan__is_completed')</b>,
    num_of_deferred_plans=Count('plan', <b>filter=Q(plan__status='deferred')</b>)
)

Обычно это Лучше не использовать .values(). Но используйте объекты (которые имеют дополнительные атрибуты), поскольку с тех пор вы сохраняете логику c, которую вы определили в своей модели, нетронутой.

...