目标:对象有两个属性:第一个属性指向由JSON数组支持的Python列表。第二个属性指向第一个属性列表中的特定索引。
问题:上面列出的第二个属性目前不起作用。
背景:源自TypeDecorator
的JSONB
的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
而不是预期的结果。明确添加astext
(MyClass.values_to_hold[1].astext
)也无济于事。
如果我设置:
MyClass.second_val_in_arr = MyClass.values_to_hold
然后second_val_in_arr
按预期返回实际数组。但是如果我尝试对数组执行索引操作(如上所述),那么它会突然返回JSONElement
。
其他信息:
MyArr
是TypeDecorator
,如下所示:
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需要特殊逻辑。)
答案 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
中的第二项。