Аннотация, чтобы считать и вернуть ноль, когда нет отношения - PullRequest
0 голосов
/ 12 сентября 2018

Учитывая следующее соотношение:

class LicenseRequest:
    license_type = models.ForeignKey(LicenseType)
    created_at = models.DateField(default=now, editable=False)

class LicenseType:
    name = models.CharField(max_length=100)
    value = models.CharField(max_length=3, unique=True)

Я хочу посчитать, сколько запросов было создано для каждого типа лицензии. Однако, поскольку я генерирую графику, я должен включить 0 (ноль) для типов лицензий без какого-либо запроса на лицензию в этот конкретный период.

Я пытался сделать то, что было предложено здесь , но это не сработало. Я могу получить счет только по тем типам лицензий, которые имеют более одного запроса лицензии.

qs = LicenseType.objects.filter(
                Q(licenserequest__created_at__range=(start_date, end_date)) | Q(licenserequest__isnull=True)
            ).annotate(rel_count=Count('licenserequest__id'))

Я мог бы найти другой способ достичь этой цели, но мне было интересно, смогу ли я сделать это с помощью аннотации.

Я использую .

Ответы [ 2 ]

0 голосов
/ 12 сентября 2018

В и выше, объект Count имеет параметр filter, поэтому мы можем указать для него следующие значения:

qs = LicenseType.objects.annotate(
    rel_count=Count(
        'licenserequest'<b>,
        filter=Q(licenserequest__created_at__range=(start_date, end_date))</b>
    )
)
qs = LicenseType.objects.annotate(
    rel_count=Count(
        'licenserequest'<b>,
        filter=Q(licenserequest__created_at__range=(start_date, end_date))</b>
    )
)

Для и ниже мы можем использовать Sum(..) выражения Case(..):

qs = LicenseType.objects.annotate(
    rel_count=Sum(Case(
        When(
            licenserequest__created_at__range=(start_date, end_date),
            then=1
        ),
        default=0,
        output_field=IntegerField()
    ))
)
0 голосов
/ 12 сентября 2018
qs = LicenseType.objects.annotate(count=Count('licenserequest__id')
condition = Q(licenserequest__created_at__range=(start_date, end_date)) & Q(licenserequest__isnull=True)
qs = qs.annotate(Case(When(condition, then=F('count')), default=0, output_field=IntegerField())

Это должно работать для предоставленного вами описания модели. Чтобы выполнить более поздний фильтр, вы не можете использовать прямой .filter (), а вместо этого использовать предложение Case / When .annotate ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...