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とプロパティがあります。一意に識別する単純なフィールドがあります。必要に応じて、さらにコードを提供できます。programProgramprogram_rawProgramraw

問題は、現在、SQLAlchemy が単にプログラム インスタンスを値ではなくパラメータとしてクエリに渡そうとしていることrawです。これにより、Error binding parameter 0 - probably unsupported type.エラーが発生します。

  • いずれにせよ、SQLAlchemy は、 を比較するときにprogram、それを使用してパラメーターのプロパティMember.program_rawと照合する必要があることを認識する必要があります。raw使用するMember.program_rawのは簡単ですが、パラメーターを正しく@program.expression変換する方法がわかりません (コンパレーターを使用しますか?)、および/またはProgram
  • SQLAlchemy は、Programインスタンスでフィルタリングするときにraw属性を使用する必要があることを認識している必要があります。

私のユースケースはおそらく少し抽象的ですが、シリアル化された RGB 値をデータベースに格納し、モデルに Color クラスを持つプロパティがあると想像してください。Color クラスでフィルタリングしたいのですが、フィルターで RGB 値を処理する必要はありません。カラークラスは、RGB 値を教えてくれます。

4

1 に答える 1

5

のソースを読んで理解しましたrelationshipComparator秘訣は、2 つのことを比較する方法を知っているプロパティのカスタムを使用することです。私の場合、それは次のように簡単です:

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 に答える