如何在Django Model中按CHOICES元组顺序对Choice字段排序
问题原因
你直接按status字段排序走的是字符串字典序,你定义的CHOICES存储值分别是H、A、R、I,按字典序默认排序结果是A(Accepted) > H(Host) > I(Invited) > R(Rejected),和你需要的顺序完全不符,所以原有配置不生效。
可用解决方案
方案1:注解自定义排序权重(最灵活,无需改动存量数据和模型存储逻辑)
在查询时通过annotate给每个状态匹配自定义排序权重,再按权重排序,示例代码如下:
from django.db.models import Case, When, IntegerField # 单次查询时添加排序逻辑 meeting_members = MeetingMember.objects.annotate( status_order=Case( When(status='H', then=1), When(status='A', then=2), When(status='R', then=3), When(status='I', then=4), output_field=IntegerField() ) ).order_by('status_order')
如果需要全局默认生效,可以把逻辑封装到自定义模型管理器中:
from django.db import models from django.db.models import Case, When, IntegerField class MeetingMemberManager(models.Manager): def get_queryset(self): return super().get_queryset().annotate( status_order=Case( When(status='H', then=1), When(status='A', then=2), When(status='R', then=3), When(status='I', then=4), output_field=IntegerField() ) ).order_by('status_order') class MeetingMember(models.Model): CHOICES = ( ("H", "Host"), ("A", "Accepted"), ("R", "Rejected"), ("I", "Invited" ) ) status = models.CharField(max_length=9, choices=CHOICES, default="I") # 替换默认管理器 objects = MeetingMemberManager()
配置后所有默认的MeetingMember.objects.all()查询都会自动按你需要的顺序排序。
方案2:调整存储值匹配字典序(适合无存量数据的新项目)
如果项目还未上线、没有历史数据,可以直接把CHOICES的存储值改成和排序顺序匹配的序列,比如:
CHOICES = ( ("1", "Host"), ("2", "Accepted"), ("3", "Rejected"), ("4", "Invited" ) )
之后直接在Meta中配置ordering = ('status',)即可生效,该方案改造成本低,但已有存量数据的项目需要做数据迁移,比较繁琐。
方案3:Django 3.2+ 用TextChoices枚举类优化可维护性
如果使用Django 3.2及以上版本,可以用内置的TextChoices定义选项,后续调整排序规则时更不容易出错:
from django.db import models class MeetingMember(models.Model): class Status(models.TextChoices): HOST = "H", "Host" ACCEPTED = "A", "Accepted" REJECTED = "R", "Rejected" INVITED = "I", "Invited" @classmethod def get_order_weight(cls): return { cls.HOST: 1, cls.ACCEPTED: 2, cls.REJECTED: 3, cls.INVITED:4 } status = models.CharField(max_length=9, choices=Status.choices, default=Status.INVITED)
写排序逻辑时可以直接复用枚举类的映射,不需要重复硬编码状态值。
内容的提问来源于stack exchange,提问作者Niloofar
相关产品推荐
相关产品推荐

