在Django中,如何通过多选CharField以任意非字母顺序排序?

Gho*_*r21 10 django sql-order-by django-models

想象一下Shirts带有sizeCharField 的模型,其值仅限于少量选择,例如"小","中","大","xlarge"等.

要按尺寸分组衬衫,您需要:

Shirts.objects.order_by('size')
Run Code Online (Sandbox Code Playgroud)

但是Django会(自然地)按字母顺序对这些组进行排序,即"大"然后"中"然后"小"然后"xlarge".我想要的是在'大'之前'中'之前'小'等.

即我自然想要做的是类似下面的伪代码:

size_order = {'small': 1, 'medium': 2, 'large': 3, 'xlarge': 4}
Shirts.objects.order_by('size_order[size]')
Run Code Online (Sandbox Code Playgroud)

实现这一目标的最佳方法是什么?

编辑:请参阅我的评论以获取有关各种建议方法的想法.我使用我正在调查的SQL ORDER BY CASE语法偶然发现了一个自定义的Manager/QuerySet方法.

Gho*_*r21 10

我发现了最接近我正在寻找的东西,即使用QuerySet.extra()方法来利用SQL的CASE WHEN/THEN语法,Django不直接支持:

CASE_SQL = '(case when size="small" then 1 when size="medium" then 2 when size="large" then 3 when size="xlarge" then 4 end)' 
Shirt.objects.extra(select={'shirt_order': CASE_SQL}, order_by=['shirt_order'])
Run Code Online (Sandbox Code Playgroud)

根据我的(人工)示例,这看起来似乎有点过分和/或肮脏,但这是我正在寻找的技巧!感谢大家对于这个问题的其他完全有效的方法,这在某种程度上间接地引发了我找出这种方法.

PS创建一个自定义模型Manager/QuerySet组合很有吸引力,它通过SQL的CASE WHEN/THEN语法为这种自定义排序提供了更原生的Django接口,但我将把它留给我自己作为另一个时间的家庭作业!

注意:CASE WHEN/THEN的语法是特定于数据库的.上面的语法适用于SQLite.对于PostgreSQL,省略括号并使用转义的单引号而不是双引号.