SQLAlchemy查询结合mypy类型检查时where子句参数类型不兼容问题的排查与解决
SQLAlchemy查询结合mypy类型检查时where子句参数类型不兼容问题的排查与解决
我来帮你拆解这个问题的根源,以及给出对应的解决办法:
问题出在哪?
你当前的写法是把Pydantic schema的属性(比如integration_create.provider_accounting_id)放在等式左侧,和SQLAlchemy模型的列(Integration.provider_accounting_id)做比较。这时候Python会直接计算这个等式的布尔值——因为左边是普通的Python数据类型(字符串、整数这类),它的__eq__方法会把右边的SQLAlchemy列对象当成普通Python对象来比较,结果是一个bool值。但SQLAlchemy的where方法需要的是SQL查询表达式(也就是ColumnElement[bool]这类类型),而不是普通布尔值,所以mypy就抛出了类型不兼容的错误。
怎么解决?
核心思路是让SQLAlchemy的列对象作为等式的左侧操作数,这样就能触发它重载的==运算符,生成符合要求的SQL查询表达式,同时满足mypy的类型检查。
修正后的代码如下:
duplicate_integration = select(Integration).where( Integration.provider_accounting_id == integration_create.provider_accounting_id, Integration.provider_webshop_id == integration_create.provider_webshop_id, Integration.user_id == user.id, )
为什么这样就可以?
SQLAlchemy的Column类重载了__eq__方法,当你用列 == 值的形式写条件时,它不会直接返回布尔值,而是生成一个ColumnElement[bool]类型的查询表达式对象——这正是where方法所期望的参数类型,mypy自然就不会再报错了。
如果有大量条件需要组合,也可以用SQLAlchemy的and_函数来包裹多个表达式,写法如下(效果和上面一致):
from sqlalchemy import and_ duplicate_integration = select(Integration).where( and_( Integration.provider_accounting_id == integration_create.provider_accounting_id, Integration.provider_webshop_id == integration_create.provider_webshop_id, Integration.user_id == user.id, ) )
备注:内容来源于stack exchange,提问作者Gronnmann
相关产品推荐
相关产品推荐

