You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.03 10:15:05