4

我有一个声明的模型,其中表存储对象的“原始”路径标识符。然后我有一个@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.错误。

  • 要么,SQLAlchemy 需要知道在比较 时program,它必须使用并将其与参数的属性相Member.program_raw匹配。只需使用即可使用raw它,但我不知道如何正确翻译参数(使用比较器?),和/或Member.program_raw@program.expressionProgram
  • SQLAlchemy 应该知道,当我按Program实例过滤时,它应该使用raw属性。

我的用例可能有点抽象,但想象一下我在数据库中存储了一个序列化的 RGB 值,并且在模型上有一个带有 Color 类的属性。我想按 Color 类进行过滤,而不必在我的过滤器中处理 RGB 值。颜色类告诉我它的 RGB 值没有问题。

4

1 回答 1

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 实例中。

于 2012-10-27T18:37:33.917 回答