Django如何实现all_in查询 筛选必填配料全在指定匹萨中的订单
Django ORM实现筛选必填配料全部属于指定披萨的订单
问题背景
现有三个Django模型如下:
class Pizza(models.Model): toppings = models.ManyToManyField(Topping) class Topping(models.Model): name = models.CharField(max_length=50) class Order(models.Model): must_have_toppings = models.ManyToManyField(Topping)
需求为筛选出must_have_toppings所有配料都属于指定Pizza对象配料的Order,之前尝试的两种方案均不符合要求:
- 使用
must_have_toppings__in查询:只要订单有任意一个配料匹配就返回,不符合全部包含的要求 - 循环叠加filter查询:返回的是包含披萨所有配料的订单,允许订单存在额外必填配料,和需求逻辑相反
解决方案
两种方案均适配MySQL数据库,无需编写原生SQL即可实现需求。
方案1:反向排除法(写法更简洁)
核心逻辑:排除所有关联了「不在披萨配料列表中」的配料的订单,剩余订单全部符合要求。
# 先获取当前披萨的所有配料ID pizza_topping_ids = my_pizza.toppings.values_list('id', flat=True) # 排除关联了非披萨配料的订单 orders = Order.objects.exclude( must_have_toppings__in=Topping.objects.exclude(id__in=pizza_topping_ids) )
方案2:聚合计数法(逻辑更直观)
核心逻辑:如果订单的必填配料总数量,和其中属于披萨配料的数量相等,说明所有必填配料都在披萨配料范围内。
from django.db.models import Count, F, Q pizza_topping_ids = my_pizza.toppings.values_list('id', flat=True) orders = Order.objects.annotate( # 统计订单必填配料总数量 total_required = Count('must_have_toppings'), # 统计订单必填配料中属于当前披萨配料的数量 matched = Count('must_have_toppings', filter=Q(must_have_toppings__in=pizza_topping_ids)) ).filter( # 两个数量相等即所有必填配料都在披萨配料中 total_required = F('matched') )
内容的提问来源于stack exchange,提问作者Ryan Pergent
相关产品推荐
相关产品推荐

