我遇到了一个问题,我试图将字符串(以db为单位)转换为小数列表。
我的代码:'
@hybrid_property
def decimals(self) -> list[Decimal]:
return [Decimal(dec) for dec in self._decimals.replace('d', '').split(';')]
@decimals.setter
def decimals(self, decimals):
self._decimals = ';'.join(str(dec) for dec in decimals)
我得到一个错误'decimals'是一个无效的关键字参数
异常堆栈:
self = <app.models.models.Test_Db object at 0x000001F2A5EAA2F0>
kwargs = {'id': 0, 'connection': 'D', 'fron': 'loop feed', 'hasRail': False, ...}
cls_ = <class 'app.models.models.Test_Db'>, k = 'decimals'
def _declarative_constructor(self, **kwargs):
"""A simple constructor that allows initialization from kwargs.
Sets attributes on the constructed instance using the names and
values in ``kwargs``.
Only keys that are present as
attributes of the instance's class are allowed. These could be,
for example, any mapped columns or relationships.
"""
cls_ = type(self)
for k in kwargs:
if not hasattr(cls_, k):
> raise TypeError(
"%r is an invalid keyword argument for %s" % (k, cls_.__name__)
)
E TypeError: 'decimals' is an invalid keyword argument for Test_Db
..envlibsite-packagessqlalchemyormdecl_base.py:1154: TypeError
您想要实现的功能类似于:
class Bar:
def __init__(self, _a):
self._a = _a
@property
def a(self):
return self._a
@a.setter
def a(self, a):
self._a = a
bar = Bar(a=1) # TypeError: Bar.__init__() got an unexpected keyword argument 'a'
Bar
的__init__
函数不知道a
,只知道_a
。
当您试图用一个属性而不是映射属性__init__
SQLAlchemy映射类时,也会发生同样的事情。
演示:
from decimal import Decimal
from sqlalchemy import Column, Integer, String, create_engine, select
from sqlalchemy.ext.hybrid import hybrid_property
from sqlalchemy.orm import Session, declarative_base
Base = declarative_base()
class Foo(Base):
__tablename__ = "foo"
id = Column(Integer, primary_key=True)
_decimals = Column(String, nullable=False)
@hybrid_property
def decimals(self) -> list[Decimal]:
return [
Decimal(dec) for dec in self._decimals.replace("d", "").split(";")
]
@decimals.setter
def decimals(self, decimals: list[Decimal]) -> None:
self._decimals = ";".join(str(d) for d in decimals)
engine = create_engine("sqlite://", future=True, echo=True)
Base.metadata.create_all(engine)
with Session(bind=engine) as session:
session.add(Foo(_decimals="d1.0;d2.0;d3.0"))
session.commit() # OK
with Session(bind=engine) as session:
session.add(Foo(decimals=[Decimal("4.0"),Decimal("5.0"),Decimal("6.0"))
session.commit() # TypeError
with Session(bind=engine) as session:
result = session.scalars(select(Foo)).first()
print(result.decimals) # [Decimal('1.0'), Decimal('2.0'), Decimal('3.0')]