私は元帳テーブルと対応するpythonクラスを持っています。 次のように私は、SQLAlchemyのを使用してモデルを定義し、あなたが見ることができるようSQLAlchemyでこのハイブリッドプロパティのSQLレベル式を実装する方法は?
class Ledger(Base):
__tablename__ = 'ledger'
currency_exchange_rate_lookup = {('CNY', 'CAD'): 0.2}
amount = Column(Numeric(10, 2), nullable=False)
currency = Column(String, nullable=False)
payment_method = Column(String)
notes = Column(UnicodeText)
@hybrid_property
def amountInCAD(self):
if self.currency == 'CAD':
return self.amount
exchange_rate = self.currency_exchange_rate_lookup[(self.currency, 'CAD')]
CAD_value = self.amount * Decimal(exchange_rate)
CAD_value = round(CAD_value, 2)
return CAD_value
@amountInCAD.expression
def amountInCAD(cls):
amount = cls.__table__.c.amount
currency_name = cls.__table__.c.currency
exchange_rate = cls.currency_exchange_rate_lookup[(currency_name, 'CAD')]
return case([
(cls.currency == 'CAD', amount),
], else_ = round((amount * Decimal(exchange_rate)),2))
は今、私は「amountInCAD」と呼ばれるハイブリッドプロパティを作成します。 Pythonレベルのゲッターが正常に動作しているようです。ただし、SQL式は機能しません。
は今、私はこのようなクエリを実行する場合:
>>>db_session.query(Ledger).filter(Ledger.amountInCAD > 1000)
SQLAlchemyのは、私は、このエラーを与える:私はハイブリッドプロパティに関するSQLAlchemyののオンラインドキュメントを調査してきました
File "ledger_db.py", line 43, in amountInCAD
exchange_rate = cls.currency_exchange_rate_lookup[(currency_name, 'CAD')]
KeyError: (Column('currency', String(), table=<ledger>, nullable=False), 'CAD')
。 http://docs.sqlalchemy.org/en/latest/orm/mapped_sql_expr.html#using-a-hybrid 私のコードをサンプルコードと比較すると、なぜ私が機能しないのか分かりません。公式の例では、cls.firstname
が値の列を参照できる場合、なぜ私のコードでcls.__table__.c.currency
はその値ではなくColumn
を返しますか?
@lljaエベリラさんに感謝します。ところで、どうやってDecimalをSQL式の中で使うことができますか?私は浮動小数点ではなく10進数であることを保証する必要があります。 –
もちろん、値は「Decimal」で始まる必要があります。前に浮動小数点数がある場合は、すでに誤った値、 'Decimal(0.3)' - > 'Decimal( '0.299999999 ...')を持っている可能性があります。 DB列には、固定精度タイプなども使用する必要があります。 DB-API *は、バインドパラメータとして与えるだけで、チェックを行うだけで、そのままPythonの 'Decimal'型をそのまま扱うべきです。 DB-APIはSQLAlchemyが使用するもので、たとえばPostgresqlの場合はpsycopg2(共通)です。 –
@lljaEverilä私は残念ながら、データベースのバックエンドでDecimalをサポートしていないSQLiteを使用しています。回避策を提案してください。 SQLレベルでのみ。私はすでにpythonレベルの装飾型を使用しています。ありがとう。 –