首页 > 解决方案 > SQLAlchemy 类型装饰器因“对象没有属性“self_group”而失败

问题描述

我有一个使用 SQLAlchemy 1.1 的旧版 Python 3 代码库,出于“原因”,它有一个类:

class jsonbool(str):
   def __bool__(self):
       return True if self == 'true' else False

此类用于 SQLAlchemy 过滤器表达式,例如query.filter(SomeTable.ABooleanColumn == anInstanceOfjsonbool).all(). 这在 1.1 中运行良好,因为jsonbool使用了类型的字符串表示(例如trueor false)。

在 SQLAlchemy 1.2 中,添加了额外的检查以防止将某些类型强制转换为布尔值。上面的工作现在失败了sqlalchemy.exc.StatementError: (builtins.TypeError) Not a boolean value: 'false'false实际上有一个实例jsonbool)。

我想用 SQLAlchemy TypeDecorator 来纠正这个问题,这将允许我在绑定到表达式时将参数转换为布尔值。我的原型只是为了让自定义类型的装饰工作,使用:

import sqlalchemy.types as types

class jsonbool(str, types.TypeDecorator):
   impl = types.Boolean

   def __bool__(self):
       return True if self == 'true' else False

唉,这个,以及我在尝试运行查询时尝试的所有类似结果都会导致AttributeError: 'Boolean' object has no attribute 'self_group'(where )。s/Boolean/WhateverImplIPick我也尝试过使用UserDefinedType具有相同结果的 a 。

jsonbool当我将它用作 SQLAlchemy 表达式的一部分时,如何更改类型的行为?

标签: pythonsqlalchemy

解决方案


ATypeDecorator是 SQLAlchemy 类型,类似于Stringor Boolean,其实例用于声明列或表达式的类型,如

foo = Column(String, ...)
bar = Column(jsonbool, ...)

使用这样的类型作为值是没有意义的,所以就像 how stris separate from一样String,您需要一个JsonBool与 分开的类jsonbool,如下所示:

class JsonBool(TypeDecorator):
    impl = Boolean

    def process_bind_param(self, value, dialect):
        return value == "true"

    def process_result_value(self, value, dialect):
        return jsonbool("true") if value else jsonbool("false")

当然,您需要更改您的定义SomeTable.ABooleanColumn才能使用此类型:

ABooleanColumn = Column(JsonBool, ...)

这对您的代码库来说可能是一个很高的要求,在这种情况下,您可以让 SQLAlchemy对对象进行自定义编译jsonbool

class jsonbool(str, ColumnElement):
    def __bool__(self):
        return True if self == 'true' else False

@compiles(jsonbool)
def _compile_jsonbool(element, compiler, **kwargs):
    if element:
        return compiler.visit_true(None)
    else:
        return compiler.visit_false(None)

推荐阅读