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

如何在Django ORM中对自关联子对象执行order_by排序?

解决方案

要实现父场馆紧跟其所有子场馆、同层级按ordering排序的需求,你需要基于根节点的排序值、是否为父场馆、自身排序值三层逻辑构建排序规则:

核心思路

  1. 同属一个父场馆的子项,和父场馆共享同一个根排序值(父场馆的ordering),确保父场馆组整体排在其他父场馆组前面。
  2. 同一根组内,父场馆优先排在所有子场馆前面。
  3. 同类型(父/子)场馆内部,按自身ordering值排序。

具体实现

使用Django ORM的Coalesce函数处理根排序值,结合布尔字段排序实现父场馆优先:

from django.db.models import Coalesce
from rest_framework import viewsets
from .models import Venue
from .serializers import VenueSerializer

class VenueViewSet(viewsets.ModelViewSet):
    queryset = Venue.objects.all()
    serializer_class = VenueSerializer

    def get_queryset(self):
        queryset = super().get_queryset()
        return queryset.order_by(
            # 根排序值:父场馆用自身ordering,子场馆用父场馆的ordering
            Coalesce('parent__ordering', 'ordering'),
            # 父场馆排在子场馆前面(-parent__isnull让True值的父场馆排前)
            '-parent__isnull',
            # 同类型场馆内部按自身ordering排序
            'ordering'
        )

替代写法(显式逻辑)

如果你更倾向于显式条件判断,可用Case/When代替Coalesce,效果完全一致:

from django.db.models import Case, When

def get_queryset(self):
    queryset = super().get_queryset()
    return queryset.order_by(
        Case(
            When(parent__isnull=True, then='ordering'),
            default='parent__ordering'
        ),
        '-parent__isnull',
        'ordering'
    )

效果验证

按上述规则排序后,数据会呈现你期望的顺序:

  1. Spain(根排序0,父场馆)
  2. Barcelona(根排序0,子场馆,自身ordering0)
  3. Castelldefels(根排序0,子场馆,自身ordering1)
  4. Girona(根排序0,子场馆,自身ordering2)
  5. Singapore(根排序1,父场馆)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 17:32:13