Вопрос по sqlite – Как я должен обрабатывать десятичные в SQLalchemy & SQLite

21

Error: User Rate Limit Exceeded

SAWarning: Dialect sqlite+pysqlite does not support Decimal objects natively

Error: User Rate Limit ExceededpkgPrice = Column(Numeric(12,2)) в SQLalchemy, все еще используя SQLite.

Этот вопрос [1]Как преобразовать десятичный Python в числовой SQLite? показывает способ использованияsqlite3.register_adapter(D, adapt_decimal) чтобы SQLite получал и возвращал Decimal, но сохранял строки, но я пока не знаю, как копаться в ядре SQLAlchemy, чтобы сделать это. Декораторы шрифтов выглядят как правильный подход, но я их пока не понимаю.

У кого-нибудь есть рецепт декоратора типа SQLAlchemy, который будет иметь числовые или десятичные числа в модели SQLAlchemy, но хранить их как строки в SQLite?

Ваш Ответ

3   ответа
15

Error: User Rate Limit Exceeded adamek
Error: User Rate Limit Exceeded
1

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

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
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы