Django queryset如何先按title排序再按自定义尺码列表顺序排序
Django 自定义size字段排序解决方案
以下是3种不同场景下的可行实现方案:
方案1:annotate + Case/When 全数据库通用方案
无需修改现有表结构,兼容所有Django支持的数据库,是适用范围最广的实现方式:
- 先导入ORM内置工具
from django.db.models import Case, When, IntegerField
- 构造带自定义排序的查询集
order_size_list = ['S', 'M', 'L', 'XL', 'XXL'] # 为每个size值映射对应的排序优先级,列表中越靠前的size优先级数值越小 size_order_rule = Case( *[When(size=size_val, then=idx) for idx, size_val in enumerate(order_size_list)], output_field=IntegerField(), # 可选:存在不在列表里的size值时,默认排到最后/最前,这里999代表排到最后 default=999 ) queryset = RawMaterial.objects.annotate( size_sort_priority=size_order_rule ).order_by('title', 'size_sort_priority')
方案2:PostgreSQL 专属简化方案
如果项目使用PostgreSQL作为数据库,可以直接调用内置的ARRAY_POSITION函数简化代码,不需要写多组When判断:
from django.db.models import F, Func, IntegerField order_size_list = ['S', 'M', 'L', 'XL', 'XXL'] size_order_rule = Func( order_size_list, F('size'), function='ARRAY_POSITION', output_field=IntegerField() ) queryset = RawMaterial.objects.annotate( size_sort_priority=size_order_rule ).order_by('title', 'size_sort_priority')
方案3:长期优化方案(size为固定枚举值时适用)
如果size取值是固定不会频繁变动的枚举值,建议直接调整模型字段结构,从根源上优化排序性能:
- 修改模型定义,把size的排序权重直接存入字段值
class RawMaterial(models.Model): SIZE_CHOICES = ( (0, 'S'), (1, 'M'), (2, 'L'), (3, 'XL'), (4, 'XXL'), ) # 存储数值类型的size权重,展示时用对应的字符名即可 size = models.IntegerField(choices=SIZE_CHOICES) title = models.CharField(max_length=200) # 其余字段省略
- 排序时直接调用字段即可,无需额外注解
queryset = RawMaterial.objects.order_by('title', 'size')
内容的提问来源于stack exchange,提问作者Kaloyan Georgiev
相关产品推荐
相关产品推荐

