2012-10-27 81 views
3

我有一個聲明模型,其中表存儲對象的「原始」路徑標識符。然後我有一個@hybrid_property,它允許直接獲取和設置由該字段標識的對象(這是而不是另一個聲明性模型)。有沒有辦法直接在這個高層次上查詢?按SQLAlchemy中的對象過濾

我可以這樣做:

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_rawProgram有一個簡單的raw字段,可以唯一標識它。如有必要,我可以提供更多代碼。

問題是,目前,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類進行過濾,而不必處理濾鏡中的RGB值。色類沒有問題告訴我它的RGB值。

回答

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__),這樣我就可以返回一個「新」計劃的所有時間。對於其他情況,實例可能應該被延遲創建並存儲在成員實例中。