为枚举字段类型指定排序顺序

11 投票
1 回答
5727 浏览
提问于 2025-04-18 06:19

我有一个模型,它使用了Enum这种字段类型:

from sqlalchemy import Column, Enum, Integer, String

class Task(Base):
    __tablename__ = 'tasks'

    id = Column(Integer, primary_key=True)
    summary = Column(String)
    priority = Column(Enum('low', 'medium', 'high'))

如果我按优先级(也就是这个 Enum 字段)来排序记录,它会按照字母顺序排序:

high
low
medium

我该如何指定这个字段的排序顺序呢?

1 个回答

10

可能还有其他方法,但我知道最简单(而且不依赖于特定数据库)的解决方案就是在 order by 语句中使用一个 case 语句

第一步,先为你的 case 语句准备一个 whens 字典,这个字典是通过获取你用来创建列的 Enum 元组来设置的:

enums = Task.priority.type.enums  # finds the Enum tuple (with the same order you originally gave it)
whens = {priority: index for index, priority in enumerate(enums)}  # dynamically creates whens dict based on the order of the Enum tuple

或者,如果你非得这样做,可以直接写死你的 whens 字典(这样做肯定不太理想,因为你需要在两个地方修改代码):

whens = {'low': 0, 'medium': 1, 'high': 2}

第二步,在 case 语句中设置你的排序逻辑:

sort_logic = case(value=Task.priority, whens=whens).label("priority")

第三步,运行你的查询,并按照你的 case 语句进行排序:

q = session.query(Task).order_by(sort_logic)  # see the sql at the end of this answer

现在你得到了一个按照原始 Enum 元组排序的查询结果:

>>> for item in q:
        print item.id, item.priority
#  now in the order you were looking for
4 low
7 low
3 medium
8 medium
2 high
6 high

仅供参考,上面的查询会生成以下 SQL 语句:

SELECT        tasks.id AS tasks_id,
              tasks.summary AS tasks_summary,
              tasks.priority AS tasks_priority 
FROM          tasks
ORDER BY CASE tasks.priority
             WHEN :param_1 THEN :param_2
             WHEN :param_3 THEN :param_4
             WHEN :param_5 THEN :param_6
         END

撰写回答