Django получить количество вложенных связанных объектов - PullRequest
1 голос
/ 25 февраля 2020

Я использую Django 2.2

У меня есть три модели

class LeadList(SafeDeleteModel):
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=128, verbose_name='Lead List Name')

    def entries_count(self):
        return LeadListEntry.objects.filter(
            dynamic_url_object__lead_list=self
        ).count()
class DynamicUrlObject(SafeDeleteModel):
    lead_list = models.ForeignKey(
        LeadList,
        on_delete=models.SET_NULL,
        blank=True,
        null=True,
        default=None,
        related_name='dynamic_url_object'
    )
class LeadListEntry(models.Model):
    dynamic_url_object = models.ForeignKey(
        'otherapp.DynamicUrlObject',
        on_delete=models.CASCADE,
        related_name='lead_list_entry'
    )
    data = models.TextField(help_text='Lead List entry data. (JSON data)', blank=False)

LeadList имеет ссылку в DynamicUrlObject. LeadList может быть связан с несколькими DynamicUrlObject экземплярами.

LeadListEntry связан с DynamicUrlObject для записи данных для каждого DynamicUrlObject экземпляра.

Я хочу получить count из LeadListEntry для конкретного LeadList.

Для этого у меня есть метод модели в модели LeadList для возврата количества записей LeadListEntry.

Но при получении списка LeadList возникает проблема N + 1 , когда entries_count вызывается для каждого объекта lead_list, который, в свою очередь, выполняет запрос на LeadListEntry, чтобы получить количество.

Я пытался использовать prefetch_related в виде, как

def get_queryset(self):
    return self.serializer_class.Meta.model.objects.filter(
        user=self.request.user
    ).prefetch_related(
        'dynamic_url_object__lead_list_entry'
    )

Но это не дает никакой пользы.

Как я могу получить count для каждого lead_list объекта без проблем с N+1?

1 Ответ

1 голос
/ 25 февраля 2020

Вы можете сделать

ll = LeadList.objects.first()  # some lead list object

le_count = LeadListEntry.objects.filter(dynamic_url_object__lead_list=ll).count()

РЕДАКТИРОВАТЬ

Вы можете использовать аннотации, как это.

from django.db.models import Count


ll = LeadList.objects.annotate(le_count=Count('dynamicurlobject__leadlistentry'))

Каждый объект в ll У набора запросов будет атрибут le_count, содержащий общее количество списков потенциальных клиентов для этого конкретного объекта.

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