django prefetch_related & Prefetch nested - PullRequest
0 голосов
/ 06 июля 2018

Я пытаюсь вернуться, для каждого UserProfile, который имеет один-ко-многим Subscription, который имеет Foreignkey для Artist и UserProfile, с каждым художником, имеющим много ReleaseGroup, количество из будущих групп выпуска, которые есть у каждой UserProfile.

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

Однако я застрял прежде, чем я начал считать ...

    context['test_totals'] = UserProfile.objects.prefetch_related(
        Prefetch('subscription_set', queryset=Subscription.objects.
                 prefetch_related(Prefetch('artist', queryset=Artist.objects.
                                           prefetch_related(Prefetch('release_groups',
                                             queryset=ReleaseGroup.objects.filter(
                                        release_date__gte=startdate
        ), to_attr='rggg')), to_attr='arti')), to_attr='arts'))

доступ к userprofile.arts|length в шаблоне возвращает общее количество подписок, но rggg и arti ничего не возвращают. Как это можно сделать?

Я пытался использовать фильтрацию по себе с, скажем, filter(profile='userprofile) `, но это возвращает ошибку. Если бы я мог фильтровать себя, я мог бы заставить это работать?

Ответы [ 2 ]

0 голосов
/ 06 июля 2018

После тонны помощи от Николаса Клюаде ЛеБланка ниже рабочий запрос:

UserProfile.objects.annotate(rgs=Count(
            Case(

                When(subscriptions__artist__release_groups__release_date__gte=startdate, then=F('subscriptions__artist__release_groups__release_date')),

                When(subscriptions__artist__release_groups__release_date__lt=startdate, then=None),

                output_field=DateField()
            )
            ))

Как предположил Николас, subscriptions - это profile related_query_name, установленное в Subscription.

0 голосов
/ 06 июля 2018
context['test_totals'] = UserProfile.objects.prefetch_related(
    Prefetch(
        'subscription_set', 
        queryset=Subscription.objects.select_related(
            'artist', 'profile').prefetch_related(
                 Prefetch(
                     'artist__release_groups',
                     queryset=ReleaseGroup.objects.filter(
                          release_date__gte=startdate
                     ), 
                     to_attr='release_groups'
                 )
            ), 
        to_attr='subscriptions'
        )
    )

У меня не было возможности проверить это, но это должно сработать.вы использовали prefetch_related для внешнего ключа artist, который не поддерживается;prefetch_related предназначен для отношений, чтобы поддерживать список элементов.Таким образом, вы предварительно выбираете subscription_set и используете select_related для исполнителя, а затем предварительно выбираете отношение artist__release_groups.теперь у вас должно быть profile_instance.subscriptions ...subscriptions[index].artist ...subscriptions[index].artist.release_groups

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

После обсуждения с OP мы хотели использовать этот метод, но фильтр Date не используется.

UserProfile.objects.annotate(
    rgs=Count(
        'subscription_set__artist__release_groups',
        filter=Q(subscription_set__artist__release_groups__release_date__gte=startdate),
    distinct=True
    )
)

Реальный ответ - использовать django.db.models Case и When в качестве ОП, и я нашел.Смотрите его ответ на законченный запрос

...