想象一个模型 Shirts
与 size
CharField,其值仅限于少数选择,例如“小”、“中”、“大”、“超大”等。
要按尺寸对衬衫进行分组,您可以:
Shirts.objects.order_by('size')
但是 Django 会(自然地)按字母顺序对组进行排序,即“大”然后“中”然后“小”然后“超大”。我想要的是在“大”之前的“中”之前有“小”等。
IE。我自然想做的是类似于以下伪代码:
size_order = {'small': 1, 'medium': 2, 'large': 3, 'xlarge': 4}
Shirts.objects.order_by('size_order[size]')
实现这一目标的最佳方法是什么?
编辑:有关各种建议方法的想法,请参阅我对下面答案的评论。我偶然发现了一种使用我正在调查的 SQL ORDER BY CASE 语法的自定义 Manager/QuerySet 方法。
最佳答案
我想出了最接近我正在寻找的东西,那就是使用 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'])
鉴于我的(人工)示例,这可能看起来有点矫枉过正和/或肮脏,但这是我正在寻找的技巧!感谢大家对这个问题的其他完全有效的方法,这在某种程度上间接地激发了我想出这种方法。
附言通过 SQL 的 CASE WHEN/THEN 语法创建一个自定义模型 Manager/QuerySet 组合,为这种自定义排序提供更 native 的 Django 接口(interface)是很诱人的,但我将把它作为自己的家庭作业留待下一次!
注意:CASE WHEN/THEN 的语法是特定于数据库的。上面的语法适用于 SQLite。对于 PostgreSQL,省略括号并使用转义单引号而不是双引号。
关于django - 在 Django 中,如何以任意非字母顺序通过多项选择 CharField 进行排序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11695994/