如何按Django模型Choices定义顺序对查询集排序?
如何让Django查询集按模型choices定义的顺序排序?
你当前的OrganizationAccount模型里定义了OrgRole这个choices列表,但直接调用OrganizationAccount.objects.all().order_by('OrgRole')是行不通的——因为OrgRole是模型类的属性,并非数据库中实际存在的字段,ORM无法识别这个排序参数。
要实现按OrgRole定义的顺序返回查询集,有两种可行方案:
方案一:通用方案(适配所有数据库)
利用Django的Case和When构建排序条件,给每个role赋值对应其在OrgRole中的索引权重,再按权重排序:
from django.db.models import Case, When, IntegerField # 生成与OrgRole顺序对应的排序条件 order_conditions = [ When(role=value, then=idx) for idx, (value, label) in enumerate(OrganizationAccount.OrgRole) ] # 执行查询并按自定义顺序排序 sorted_accounts = OrganizationAccount.objects.all().annotate( role_order=Case(*order_conditions, output_field=IntegerField()) ).order_by('role_order')
这个方法的核心是通过annotate给每条记录添加一个临时字段role_order,值为该记录的role在OrgRole列表中的位置索引,最后按这个临时字段排序就能得到你想要的顺序。
方案二:PostgreSQL专属方案(更简洁)
如果你的项目使用PostgreSQL数据库,可以利用数据库的ARRAY_POSITION函数直接排序:
from django.db.models import Func, F class ArrayPosition(Func): function = 'ARRAY_POSITION' template = "%(function)s(%(expressions)s, %(field)s)" # 按OrgRole的定义顺序排序 sorted_accounts = OrganizationAccount.objects.all().order_by( ArrayPosition( list(dict(OrganizationAccount.OrgRole).keys()), F('role') ) )
这里把OrgRole的所有value转成数组,用ARRAY_POSITION获取每个role在数组中的位置,直接按这个位置排序即可。
内容的提问来源于stack exchange,提问作者Dark Angel
相关产品推荐
相关产品推荐

