django prefetch_related & 预取嵌套

django prefetch_related & Prefetch nested

我正在尝试 return,对于每个 UserProfile,它具有一对多 Subscription,它具有 ArtistUserProfile,每个艺术家有很多 ReleaseGroup,每个 UserProfilecountfuture 发行组.

简而言之:我想 return 每个用户拥有的所有订阅的即将发布的总数。

但是我还没来得及数数就卡住了...

    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 模板中的 return 订阅总数,但 rgggarti return 什么都没有。如何做到这一点?

我尝试使用 filter(profile='userprofile)` 对自身进行过滤,但 return 是一个错误。如果我可以对自己进行过滤,我可能会让它起作用吗?

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'
        )
    )

我还没有机会对此进行测试,但它应该可以工作。您在不支持的外键 artist 上使用 prefetch_related; 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 CaseWhen 作为 OP,我发现了。查看他对已完成查询的回答

在 Nicholas Cluade LeBlanc 的大量帮助下,下面是工作查询:

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()
            )
            ))

正如 Nicholas 所建议的,subscriptionsprofile related_query_nameSubscription