SQLAlchemy与Postgres:属性返回JSONElement而不是结果

时间:2017-08-03 08:43:22

标签: python postgresql sqlalchemy

目标:对象有两个属性:第一个属性指向由JSON数组支持的Python列表。第二个属性指向第一个属性列表中的特定索引。

问题:上面列出的第二个属性目前不起作用。

背景:源自TypeDecoratorJSONB的SQLAlchemy属性按预期工作。当尝试索引属性(例如,提取数组中的第二个值)时,我得到JSONElement(从BinaryExpression派生而来)而不是实际结果。

我班级的属性定义如下:

class MyClass...
    values_to_hold = Column(MyArr)

MyClass.second_val_in_arr = MyClass.values_to_hold[1]

second_val_in_arr会返回JSONElement而不是预期的结果。明确添加astextMyClass.values_to_hold[1].astext)也无济于事。

如果我设置:

MyClass.second_val_in_arr = MyClass.values_to_hold

然后second_val_in_arr按预期返回实际数组。但是如果我尝试对数组执行索引操作(如上所述),那么它会突然返回JSONElement

其他信息:

MyArrTypeDecorator,如下所示:

class MyArr(TypeDecorator):
    impl = JSONB

    def coerce_compared_value(self, op, value):
        return self.impl.coerce_compared_value(op, value)

    def process_result_value(self, value, dialect):
        if value:
            return list(value)
        else:
            return list()

(注意coerce_compared_value被显式覆盖,因为根据docs JSON需要特殊逻辑。)

1 个答案:

答案 0 :(得分:1)

作业

MyClass.second_val_in_arr = MyClass.values_to_hold[1]

只会将JSONElement作为常规属性添加到类中。 SQLAlchemy不会以任何特殊方式处理它,因此该类的实例将从类中查找属性,从而生成原始JSONElement。而是定义hybrid attribute

from sqlalchemy.ext.hybrid import hybrid_property

class MyClass(...):

    values_to_hold = Column(MyArr)

    @hybrid_property
    def second_val_in_arr(self):
        return self.values_to_hold[1]

当通过类访问时,混合将在查询上下文中充当JSONElement / BinaryExpression。当在类的实例上访问时,它将返回values_to_hold中的第二项。