我有一个声明的模型,其中表存储对象的“原始”路径标识符。然后我有一个@hybrid_property
,它允许直接获取和设置由该字段标识的对象(不另一个声明性模型)。有没有办法直接在这个高级别查询?
我可以这样做:
session.query(Member).filter_by(program_raw=my_program.raw)
我希望能够做到这一点:
session.query(Member).filter_by(program=my_program)
其中my_program.raw == "path/to/a/program"
Member
有一个字段program_raw
和一个属性program
,它可以获取正确的Program
实例并设置相应的program_raw
值。 Program
有一个简单的raw
字段,可以唯一标识它。如有必要,我可以提供更多代码。
问题是,目前,SQLAlchemy只是尝试将程序实例作为参数传递给查询,而不是其raw
值。这会导致Error binding parameter 0 - probably unsupported type.
错误。
program
时,它必须使用Member.program_raw
并将其与参数的raw
属性进行匹配。只需使用Member.program_raw
即可使用@program.expression
,但我无法弄清楚如何正确翻译Program
参数(使用比较器?)和/或Program
个实例进行过滤时,它应该使用raw
属性。我的用例可能有点抽象,但想象一下,我在数据库中存储了一个序列化的RGB值,并在模型上有一个带有Color类的属性。我想通过Color类进行过滤,而不必处理我的过滤器中的RGB值。颜色类没有问题告诉我它的RGB值。
答案 0 :(得分:5)
通过阅读relationship
的来源计算出来。诀窍是为属性使用自定义Comparator
,它知道如何比较两件事。就我而言,它很简单:
from sqlalchemy.ext.hybrid import Comparator, hybrid_property
class ProgramComparator(Comparator):
def __eq__(self, other):
# Should check for case of `other is None`
return self.__clause_element__() == other.raw
class Member(Base):
# ...
program_raw = Column(String(80), index=True)
@hybrid_property
def program(self):
return Program(self.program_raw)
@program.comparator
def program(cls):
# program_raw becomes __clause_element__ in the Comparator.
return ProgramComparator(cls.program_raw)
@program.setter
def program(self, value):
self.program_raw = value.raw
注意:就我而言,Program('abc') == Program('abc')
(我已覆盖__new__
),所以我可以随时返回“新”程序。对于其他情况,实例应该可以延迟创建并存储在Member实例中。