2012-12-29 61 views
2

我想在SQLAlchemy之上創建一個自定義接口,以便透明地支持一些預定義的混合屬性。在SQLAlchemy中創建混合屬性的自定義元類

具體來說,我想創建一個類SpecialColumn和元類,這樣,當用戶添加SpecialColumn作爲一個類的屬性,我的自定義元類取代有兩個SQLAlchemy的Column s表示屬性,並補充說,獲取並設置混合屬性這兩列作爲元組。 這裏是我的方法至今:

首先,我定義我的專欄類型:

class SpecialColumn(object): 
    pass 

然後,我定義的元類從DeclarativeMeta繼承其掃描的SpecialColumn實例類,並有兩個Column替換它們S和混合性(定義爲閉合):

class MyDeclarativeMeta(DeclarativeMeta): 

    def __new__(cls, name, bases, attrs): 
      for name, col in attrs.items(): 
       if isinstance(col, SpecialColumn): 
        # Replacing the column 
        del attrs[name] 
        col1_name = '_{0}_1'.format(name) 
        col2_name = '_{0}_2'.format(name) 
        attrs[col1_name] = Column(...) 
        attrs[col2_name] = Column(...) 
        # Adding the hybrid property 
        def getter(self): 
         return (getattr(self, col1_name), getattr(self, col2_name)) 
        attrs[name] = hybrid_property(getter) 

最後,我構造的declarative_base一個實例用它,並讓用戶定義與新基類:

MyBase = declarative_base(metaclass=MyDeclarativeMeta) 

class MyClass(MyBase): 
    col1 = SpecialColumn() 
    col2 = Column(...) 

現在對於我的問題: 首先,我的方法是否正確? 其次,我如何使用元類添加setter?這樣做是否正確:

def setter(self, (v1, v2)): 
    setattr(self, col1_name, v1) 
    setattr(self, col2_name, v2) 

然後乾脆就做attrs[name].setter(setter)

回答

7

沒有必要爲SQLAlchemy映射類使用元類,因爲我們提供了大量的events以在創建和/或映射類時添加要素。 mapper_configured可能是很好的在這裏,這如果你在0.8就可以申請到MyBase直接:

@event.listens_for(MyBase, 'mapper_configured') 
def get_special_columns(mapper, cls): 
    for attrname in dir(cls): 
     val = getattr(cls, attrname) 
     if isinstance(val, SpecialColumn): 
      name1, name2 = "_%s_1" % attrname, "_%s_2" % attrname 
      setattr(cls, name1, Column(...)) 
      setattr(cls, name2, Column(...)) 

      @hybrid_property 
      def myhybrid(self): 
       return getattr(self, name1), getattr(self, name2) 

      @myhybrid.setter 
      def myhybrid(self, value): 
       setattr(self, name1, value[0]) 
       setattr(self, name2, value[1]) 

      setattr(cls, attrname, myhybrid) 

注意,SETATTR()是去這裏,簡單扼要的最佳途徑。

+0

感謝您的回覆,以及SQLAlchemy! – mskel