Две аннотации в одном запросе - PullRequest
0 голосов
/ 14 октября 2018

Я пытаюсь создать набор запросов для подсчета, набор запросов включает три модели.

class Owner(models.Model): name = models.CharField(max_length=10, null=False)

class Location(models.Model): name = models.CharField(max_length=10, null=False) owner = models.ForeignKey(Owner, on_delete=models.SET_NULL, null=True, blank=True)

class Asset(models.Model): name = models.CharField(max_length=10, null=false) owner = models.ForeignKey(Owner, on_delete=models.SET_NULL, null=True, blank=True) location = models.ForeignKey(Location, on_delete=models.SET_NULL, null=True, blank=True)

Я пытаюсь подсчитать количество Локаций для владельца и Активы для владельца, я могу добиться этого в виде двух отдельных наборов запросов следующим образом:

locations = Owner.objects.all().annotate(locations=Count('location'))

assets = Owner.objects.all().annotate(assets=Count('asset'))

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

| Owner | Assets | Locations | |--------+--------+-----------| | owner1 | 10 | 3 | | owner2 | 100 | 20 | | owner3 | 70 | 50 |

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

Приведенный ниже запрос дает мне одинаковые числа как для объекта, так и для местоположения

queryset = Owner.objects.all().annotate(assets=Count('asset'), locations=Count('location'))

или

Запрос ниже даетмне большие числа для активов и местоположения

queryset = Owner.objects.all().annotate(assets=Count('asset')).annotate(locations=Count('location'))

Я могу сделать это напрямую с помощьюth SQL, но я надеюсь, что не идти по этому пути.

1 Ответ

0 голосов
/ 14 октября 2018

Спасибо, Нара, я попробовал другую перестановку того, что вы предложили, и это сработало.

queryset = Owner.objects.all().annotate(assets=Count('asset', distinct=True), locations=Count('location', distinct=True))

Вот как это выглядит из оболочки Django.

>>> from inventory.models import *
>>> from django.db.models import Count
>>> queryset = Owner.objects.all().annotate(assets=Count('asset', distinct=True), locations=Count('location', distinct=True))
>>> vars(queryset[0])
{'_state': <django.db.models.base.ModelState object at 0x0427B230>, 'id': 1, 'name': 'Owner 1', 'assets': 5, 'locations': 4}
>>> vars(queryset[1])
{'_state': <django.db.models.base.ModelState object at 0x0427B2D0>, 'id': 2, 'name': 'Owner 2', 'assets': 3, 'locations': 4}
>>> vars(queryset[2])
{'_state': <django.db.models.base.ModelState object at 0x0427B4D0>, 'id': 3, 'name': 'Owner 3', 'assets': 2, 'locations': 6}

Как вы можете видеть, это дает мне как активы, так и количество мест.

...