使用dataclass+mapper_registry.mapped的SQLAlchemy类无法实例化问题
报错原因与解决方案
问题产生原因
- Python装饰器的执行逻辑是从靠近类的装饰器开始,依次向远离类的装饰器执行,最终外层装饰器的返回值会替换原类。
- 你当前的装饰器顺序是
@dataclass在下层、@mapper_registry.mapped在上层,执行逻辑等价于mapper_registry.mapped(dataclass(Token)):@dataclass首先生成了接收name、symbol、decimals三个参数的构造方法,随后执行的SQLAlchemy映射装饰器默认会自动生成仅接收self的无参构造方法,直接覆盖了dataclass生成的构造方法,因此实例化时传参就会抛出参数数量不匹配的错误。
解决方案
方案1:调换装饰器顺序(最常用)
将@dataclass放在更靠近类的位置,保证dataclass生成的构造方法不会被SQLAlchemy覆盖,修改后代码如下:
from dataclasses import dataclass from sqlalchemy import String, Integer, Column, Table from sqlalchemy.orm import registry mapper_registry = registry() # 调换两个装饰器的顺序 @mapper_registry.mapped @dataclass class Token: __table__ = Table( "token", mapper_registry.metadata, Column("name", String(), primary_key=True), Column("symbol", String(), nullable=False), Column("decimals", Integer(), nullable=False), ) name: str symbol: str decimals: int # 可正常实例化 Token("name", "symbol", 1)
方案2:关闭SQLAlchemy的自动构造方法生成
如果你不想调整装饰器顺序,可以给mapped装饰器传入init=False参数,告知SQLAlchemy不要自动生成构造方法,沿用dataclass生成的构造方法即可:
@dataclass @mapper_registry.mapped(init=False) class Token: # 其余代码保持不变
内容的提问来源于stack exchange,提问作者José D.
相关产品推荐
相关产品推荐

