【问题标题】:django prefetch_related & Prefetch nesteddjango prefetch_related & Prefetch 嵌套
【发布时间】:2018-12-15 03:48:35
【问题描述】:

我正在尝试返回,对于每个UserProfile,它有一对多的Subscription,它对ArtistUserProfile 都有一个外键,每个艺术家都有很多ReleaseGroup,每个UserProfile 拥有的未来 发布组的count

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

但是我在数数之前就卡住了……

    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 进行过滤,但这会返回错误。如果我可以过滤自我,我可能可以让它工作?

【问题讨论】:

    标签: django django-orm


    【解决方案1】:
    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讨论后,我们想使用这种方法,但没有使用日期过滤器。

    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,我发现。查看他对已完成查询的回答

    【讨论】:

      【解决方案2】:

      经过 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 中设置的。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-10-07
        • 2018-05-24
        • 1970-01-01
        • 2013-09-26
        • 1970-01-01
        • 2016-11-28
        • 1970-01-01
        相关资源
        最近更新 更多