如何排除具有空预取相关字段的行

问题描述 投票:0回答:2

我将prefetch_relatedPrefetch一起使用:

prefetch_qs = Offer.objects.filter(price__gt=1000)
prefetch = Prefetch('offers', queryset=prefetch_qs)

如何排除报价空的行?它不起作用,因为注释计入了所有报价(未在prefetch中过滤):

filtered_qs = Product.objects.annotate(
    offers_count=Count('offers')
).filter(
    offers_count__gt=0
).prefetch_related(
    prefetch      
)
python django django-orm
2个回答
2
投票

Prefetch正在作为产品查询之后的第二个查询执行,因此无法基于预取过滤出产品。您需要将预取过滤作为子查询或在您要进行的Count内重复进行。

为了使计数工作,请尝试以下操作:

filtered_qs = Product.objects.annotate(
    offers_count=Count('offers', filter=Q(offers__price__gt=1000))
).filter(
    offers_count__gt=0
).prefetch_related(
    prefetch
)

为了使用子查询来完成它,您需要这样的东西:

filtered_qs = Product.objects.annotate(
    offers_count=Subquery(
        prefetch_qs.filter(product=OuterRef('pk'))
            .values('product')
            .annotate(count=Count('pk'))
            .values('count')
    )
).filter(
    offers_count__gt=0
).prefetch_related(
    prefetch
)

[子查询方法可能看起来有点难以理解,为什么这样做了,我试图在一个老问题here中解释它


1
投票

为补充@Todor答案:您可以创建自定义子查询类型以简化第二种方法并允许重用。

class SubqueryCount(Subquery):
    template = '(SELECT COUNT(*) FROM (%(subquery)s) _sub)'
    output_field = IntegerField()

filtered_qs = Product.objects.annotate(
    offers_count=SubqueryCount(prefetch_qs.filter(product=OuterRef('pk'))
).filter(
    offers_count__gt=0
).prefetch_related(
    prefetch
)
© www.soinside.com 2019 - 2024. All rights reserved.