如何在Django ORM中对自关联子对象执行order_by排序?
解决方案
要实现父场馆紧跟其所有子场馆、同层级按ordering排序的需求,你需要基于根节点的排序值、是否为父场馆、自身排序值三层逻辑构建排序规则:
核心思路
- 同属一个父场馆的子项,和父场馆共享同一个根排序值(父场馆的
ordering),确保父场馆组整体排在其他父场馆组前面。 - 同一根组内,父场馆优先排在所有子场馆前面。
- 同类型(父/子)场馆内部,按自身
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' )
效果验证
按上述规则排序后,数据会呈现你期望的顺序:
- Spain(根排序0,父场馆)
- Barcelona(根排序0,子场馆,自身ordering0)
- Castelldefels(根排序0,子场馆,自身ordering1)
- Girona(根排序0,子场馆,自身ordering2)
- Singapore(根排序1,父场馆)
内容的提问来源于stack exchange,提问作者kunambi
相关产品推荐
相关产品推荐

