ada*_*mek 22 sqlite sqlalchemy decimal type-conversion
当我使用带有SQLite数据库引擎的数值列时,SQLalchemy会给出以下警告.
SAWarning:Dialect sqlite + pysqlite本身不支持Decimal对象
我正在尝试找出pkgPrice = Column(Numeric(12,2))在SQLalchemy中使用SQLite时最好的方法.
这个问题[1] 如何将Python十进制转换为SQLite数字?显示了一种使用sqlite3.register_adapter(D, adapt_decimal)SQLite接收和返回Decimal的方法,但存储了Strings,但我不知道如何深入研究SQLAlchemy核心来做到这一点.类型装饰器看起来是正确的方法,但我还没有搞定它们.
有没有人在SQLAlchemy模型中有一个SQLAlchemy Type装饰器配方,它将具有数字或十进制数字,但是在SQLite中将它们存储为字符串?
Jos*_*sad 18
由于看起来你正在使用小数作为货币值,我建议你做安全的事情,并将货币的价值存储在其最低面额,例如1610美分而不是16.10美元.然后您可以使用Integer列类型.
它可能不是您期望的答案,但它解决了您的问题,通常被认为是理智的设计.
van*_*van 16
from decimal import Decimal as D
import sqlalchemy.types as types
class SqliteNumeric(types.TypeDecorator):
impl = types.String
def load_dialect_impl(self, dialect):
return dialect.type_descriptor(types.VARCHAR(100))
def process_bind_param(self, value, dialect):
return str(value)
def process_result_value(self, value, dialect):
return D(value)
# can overwrite the imported type name
# @note: the TypeDecorator does not guarantie the scale and precision.
# you can do this with separate checks
Numeric = SqliteNumeric
class T(Base):
__tablename__ = 't'
id = Column(Integer, primary_key=True, nullable=False, unique=True)
value = Column(Numeric(12, 2), nullable=False)
#value = Column(SqliteNumeric(12, 2), nullable=False)
def __init__(self, value):
self.value = value
Run Code Online (Sandbox Code Playgroud)
这是受@van 和@JosefAssad 启发的解决方案。
class SqliteDecimal(TypeDecorator):
# This TypeDecorator use Sqlalchemy Integer as impl. It converts Decimals
# from Python to Integers which is later stored in Sqlite database.
impl = Integer
def __init__(self, scale):
# It takes a 'scale' parameter, which specifies the number of digits
# to the right of the decimal point of the number in the column.
TypeDecorator.__init__(self)
self.scale = scale
self.multiplier_int = 10 ** self.scale
def process_bind_param(self, value, dialect):
# e.g. value = Column(SqliteDecimal(2)) means a value such as
# Decimal('12.34') will be converted to 1234 in Sqlite
if value is not None:
value = int(Decimal(value) * self.multiplier_int)
return value
def process_result_value(self, value, dialect):
# e.g. Integer 1234 in Sqlite will be converted to Decimal('12.34'),
# when query takes place.
if value is not None:
value = Decimal(value) / self.multiplier_int
return value
Run Code Online (Sandbox Code Playgroud)
就像@Jinghui Niu提到的,当十进制作为字符串存储在sqlite中时,某些查询并不总是按预期运行,例如session.query(T).filter(T.value > 100),或者像sqlalchemy.sql这样的东西。 expression.func.min,甚至 order_by,因为 SQL 比较字符串(例如字符串中的“9.2”>“19.2”)而不是我们在这些情况下预期的数值。
| 归档时间: |
|
| 查看次数: |
15280 次 |
| 最近记录: |