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

如何基于多对多关系存在性排序(Django披萨示例)

单条Django查询实现配料排序与标记需求

问题背景

Django模型定义

class Topping(models.Model):
    order = models.IntegerField()
    name = models.CharField(max_length=250)

class Pizza(models.Model):
    toppings = models.ManyToManyField(Topping)

已创建的配料实例

Topping.objects.create(order=1, name="tomato")
Topping.objects.create(order=2, name="cheese")
Topping.objects.create(order=3, name="olives")
Topping.objects.create(order=4, name="salami")
Topping.objects.create(order=5, name="onion")
Topping.objects.create(order=6, name="rocket")

需求说明

现有一个包含tomato、cheese和salami的披萨,需要获取所有Topping数据:

  • 排序规则:优先按披萨是否拥有该配料排序(拥有的在前),再按order字段升序排列
  • 每个配料需标记是否被披萨拥有,期望结果结构如下:
[
    {"id": 1, "name": "tomato", "has_topping": True},
    {"id": 2, "name": "cheese", "has_topping": True},
    {"id": 4, "name": "salami", "has_topping": True},
    {"id": 3, "name": "olives", "has_topping": False},
    {"id": 5, "name": "onion", "has_topping": False},
    {"id": 6, "name": "rocket", "has_topping": False},
]

(注:原示例中salami和olives的ID存在笔误,已修正)

解决方案:单条数据库查询实现

可以通过Django ORM的annotate结合Case/When表达式,在单条查询中完成标记和排序逻辑,无需分两次查询再用Python处理。

实现代码

# 先获取目标披萨实例(根据实际场景替换获取方式)
pizza = Pizza.objects.get(...)  # 例如:Pizza.objects.filter(toppings__name='tomato').first()

# 单条查询完成需求
toppings_queryset = Topping.objects.annotate(
    has_topping=Case(
        When(id__in=pizza.toppings.values_list('id', flat=True), then=Value(True)),
        default=Value(False),
        output_field=BooleanField()
    )
).order_by('-has_topping', 'order')

# 转换为期望的字典结构
result = [
    {"id": topping.id, "name": topping.name, "has_topping": topping.has_topping}
    for topping in toppings_queryset
]

代码说明

  1. 标记has_topping:通过annotate添加临时字段has_topping,使用Case/When判断当前配料ID是否在目标披萨的配料ID列表中,存在则返回True,否则返回False。
  2. 排序规则:order_by('-has_topping', 'order')先按has_topping降序排列(True值排在False前面),再按order字段升序排列,完全匹配需求。
  3. 性能优势:所有逻辑在数据库层面完成,仅需一次查询,避免了多次查询后用Python处理数据的额外开销。

内容的提问来源于stack exchange,提问作者run_the_race

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.19 16:10:32