首页 > 解决方案 > django prefetch_related & Prefetch 嵌套

问题描述

我试图返回,对于每个UserProfile,它有一个一对多的Subscription,它有一个外键到两者ArtistUserProfile并且每个艺术家都有很多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返回订阅总数,但rgggarti返回任何内容。如何才能做到这一点?

我尝试使用filter(profile='userprofile)` 对 self 进行过滤,但这会返回错误。如果我可以过滤自我,我可能会让这个工作?

标签: djangodjango-orm

解决方案


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。查看他对完成查询的回答


推荐阅读