在DRF中如何排序列表,使有关联Blog的用户优先、再按用户ID排序
解决方案
你可以通过Django ORM的注解功能给用户增加「是否存在关联Blog」的标识,再基于该标识做自定义排序即可,具体修改如下:
步骤1:导入依赖模块
首先在视图文件头部导入需要的ORM工具:
from django.db.models import Exists, OuterRef
步骤2:重写视图的get_queryset方法
修改原有UserAPIView,自定义查询逻辑和排序规则:
class UserAPIView(ListAPIView): serializer_class = UserSerializer def get_queryset(self): # 子查询判断当前用户是否有关联的Blog实例 has_blog = Exists(Blog.objects.filter(user=OuterRef('pk'))) # 给查询集新增has_blog注解字段,先按是否有Blog降序,再按用户ID升序排序 return User.objects.annotate( has_blog=has_blog ).order_by('-has_blog', 'id')
实现说明
Exists是Django专门用于存在性检查的子查询工具,性能远高于统计关联数量的方案,只需判断有没有关联数据,不需要计算具体数值- 注解生成的
has_blog为布尔类型,True代表用户有绑定的Blog,False代表没有 - 排序规则中
-has_blog代表按布尔值倒序,布尔值在数据库中会以1(True)、0(False)存储,所以有Blog的用户会全部排在最前面 - 后续的
id升序规则会对没有Blog的用户生效,按用户ID从小到大排列
兼容低版本Django方案
如果你使用的Django版本低于3.0(不支持Exists语法),可以用条件注解实现相同效果:
from django.db.models import Case, When, BooleanField class UserAPIView(ListAPIView): serializer_class = UserSerializer def get_queryset(self): return User.objects.annotate( has_blog=Case( When(blog__isnull=False, then=True), default=False, output_field=BooleanField() ) ).order_by('-has_blog', 'id')
内容的提问来源于stack exchange,提问作者Avik Pradhan
相关产品推荐
相关产品推荐

