Django关联查询:筛选拥有至少一个Deal的Retailer
获取拥有至少一个Deal的Retailer列表
你可以通过Django的反向关联查询来筛选出关联至少一个Deal的Retailer,这里有两种常用方案,都能解决你的需求:
方法一:用filter+distinct快速筛选
直接过滤出关联Deal不为空的Retailer,并用distinct()避免重复(如果一个Retailer有多个Deal,filter会返回多条重复记录):
修改你的上下文处理器如下:
def retailers(request): return { 'stores': Retailer.objects.filter(deal__isnull=False).distinct().order_by('company') }
细节说明:
deal__isnull=False:因为Deal模型里的retailer是外键,Django会自动为Retailer创建反向关联查询字段deal。如果你的外键设置了related_name(比如related_name='deals'),记得把这里的deal换成对应的名称,比如deals__isnull=False。这个条件会筛选出所有有至少一个关联Deal的Retailer。distinct():确保同一个Retailer即使关联多个Deal,也只会在结果里出现一次。
方法二:用annotate计数筛选(附带Deal数量)
如果之后需要用到每个Retailer的Deal数量,推荐用这种方法——给每个Retailer添加一个Deal计数字段,再筛选计数大于0的:
from django.db.models import Count def retailers(request): return { 'stores': Retailer.objects.annotate(num_deals=Count('deal')).filter(num_deals__gt=0).order_by('company') }
细节说明:
annotate(num_deals=Count('deal')):给每个Retailer对象新增num_deals属性,值为该Retailer关联的Deal总数。filter(num_deals__gt=0):只保留Deal数量大于0的Retailer,也就是符合你需求的Retailer。
两种方案都能达成目标,如果你只需要筛选Retailer,第一种更简洁;如果需要同时获取每个Retailer的Deal数量,第二种更实用。
内容的提问来源于stack exchange,提问作者John Rogerson




