欢迎光临
我们一直在努力

sqlalchemy.exc.ArgumentError: The “whens” argument to case(), when referring to a sequence of items, is now passed as a series of positional elements, rather than as a list.

对于正在从 SQLAlchemy 1.3 或更早版本迁移到 1.4/2.0 的个人站长或技术开发者来说,可能会在使用 case() 表达式构造复杂查询时遇到一个常见的参数错误。这个错误明确指出 whens 参数的用法已发生变化,不再接受一个包含所有条件元组的列表作为关键字参数,而是要求这些元组作为一系列独立的位置参数传入。

错误现象分析

当你尝试按照旧版 SQLAlchemy 的习惯,将一组条件-结果对的列表赋值给 whens 关键字参数时,你会收到以下错误:

sqlalchemy.exc.ArgumentError: The "whens" argument to case(), when referring to a sequence of items, is now passed as a series of positional elements, rather than as a list.

这是因为在 SQLAlchemy 1.4 及之后的版本中,对于 case() 表达式,如果你需要传递多个条件和结果的配对,你需要使用位置参数的方式,而不是将它们包裹在一个名为 whens 的列表中。

错误的用法示例 (导致 ArgumentError)

假设我们有一个用户表 User,我们想要根据年龄对用户进行分组判断。

from sqlalchemy import case, select, Column, Integer, String
# 假设 User 是一个映射好的 ORM 类

conditions = [
    (User.age < 18, '少年'),
    (User.age >= 60, '老年')
]

# 错误用法:将列表赋值给 whens 关键字参数
# stmt = select(User.name, case(whens=conditions, else_='成年').label('AgeGroup'))
# 运行此行会触发 ArgumentError

解决方案:使用位置参数解包 ***** 运算符

解决这个问题的最简单和最Pythonic的方法是使用星号 (*****) 解包运算符,将你的条件列表解包成单独的位置参数,直接传递给 case() 函数。

步骤 1: 准备条件列表

你的条件列表结构保持不变:一个包含 (condition, result) 元组的列表。

conditions = [
    (User.age < 18, '少年'),
    (User.age >= 60, '老年'),
    (User.is_admin == True, '管理员') # 增加一个布尔条件示例
]

步骤 2: 使用 ***** 运算符解包

conditions 列表使用 ***** 解包,使其元素直接作为位置参数传入 case() 函数。

from sqlalchemy import case, select, Column, Integer, String, Boolean

# 假设 User 类定义如下 (简化)
class User:
    age = Column(Integer)
    name = Column(String)
    is_admin = Column(Boolean)

# 正确用法:使用 * 解包列表,将其作为位置参数传递
stmt_correct = select(
    User.name,
    case(
        *conditions, 
        else_='成年/普通用户'
    ).label('AgeGroup')
)

# 示例:打印生成的 SQL (使用 PostgreSQL 语法)
# 假设我们已经创建了会话和映射
# print(str(stmt_correct.compile(compile_kwargs={"literal_binds": True}))) 

生成的 SQL 结构(取决于你的 Dialect)大致如下:

SELECT user.name, 
CASE 
  WHEN user.age < 18 THEN '少年' 
  WHEN user.age >= 60 THEN '老年' 
  WHEN user.is_admin = true THEN '管理员' 
  ELSE '成年/普通用户' 
END AS "AgeGroup" 
FROM user

总结

当你在 SQLAlchemy 1.4/2.0+ 中使用 case() 表达式时,记住条件对 (condition, result) 必须作为位置参数传递。如果你从列表中动态构建这些条件,务必使用 Python 的 ***** 解包操作符,避免再使用 whens= 关键字参数来传递整个列表,从而彻底解决 ArgumentError

【本站文章皆为原创,未经允许不得转载】:汤不热吧 » sqlalchemy.exc.ArgumentError: The “whens” argument to case(), when referring to a sequence of items, is now passed as a series of positional elements, rather than as a list.
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址