2012-04-26 26 views
0

私はSyncEntitiesクラスを持っています(下記参照)。SQLAlchemyでは、どのように動的関係を作成しますか?

SyncEntitiesクラスに関連する他のいくつかのクラス(以下に示す商品タイプなど)があります。

私の基本サブクラスのすべてはuuidKey = Column(String, primary_key=True)

このコラムを持っているSEがSyncEntitiesのインスタンスであると仮定します。 se.entityKindは、Baseサブクラスの名前です。

se.entityKindクラスのse.uuidKeyフィルタリング対象のオブジェクトをクエリするにはどうすればよいですか?

class SyncEntities(Base): 
    __tablename__ = 'SyncEntities' 

    uuidKey = Column(String, primary_key=True) 
    dateCreated = Column(DateTime, index=True) 
    dateModified = Column(DateTime, index=True) 
    dateSynced = Column(DateTime, index=True) 
    username = Column(String) 
    entityKind = Column(String) 
    deleted = Column(Boolean) 

    def __init__(self, entity, security): 
     self.uuidKey = newUUID() 
     self.dateCreated = security.now 
     self.dateModified = security.now 
     self.dateSynced = security.then 
     self.username = security.username 
     self.entityKind = entity.__tablename__ 
     self.deleted = False 

    def modified(self, security): 
     self.dateModified = security.now 
     self.username = security.username 

class CommodityTypes(Base): 
    __tablename__ = 'CommodityTypes' 
    uuidKey = Column(String, ForeignKey('SyncEntities.uuidKey'), primary_key=True) 
    myName = Column(String, unique = True) 
    sortKey = Column(Integer, unique = True) 

    mySyncEntity = relationship("SyncEntities") 

    def __init__(self, security, myName, sortKey): 
     self.syncEntity = SyncEntities(self, security) 
     self.uuidKey = self.syncEntity.uuidKey 
     self.myName = myName 
     self.sortKey = sortKey 

答えて

2

構造は、ここでは「ポリモーフィックな関連」として、しかし全く同じではない、似ている、とあなたはこのブログの記事で、このパターンで約読むことができます:http://techspot.zzzeek.org/2007/05/29/polymorphic-associations-with-sqlalchemy/。これは古い投稿ですが、http://techspot.zzzeek.org/files/2007/discriminator_on_association.pyの例は後で更新例として追加されました。

このケースは、CommodityTypesのようなオブジェクトが単一のSyncEntitiesを参照するだけで、通常の多態性の関連では複数ではないという点で少し異なります。 SyncEntitiesは、ローカルでentityKindを持っているので、関連するオブジェクトの単一のタイプだけを参照することもできます。

このデザインの潜在的な問題は、特定のSyncEntitiesインスタンスを指すuuidKeyを持つが、 "entityKind"と一致するタイプではない他のテーブルに行を持つことができることです。 CommodityTypesとSyncEntitiesの関係が実際に一対一である場合、すべてが変更されます。このパターンは実際には単純な結合テーブル継承であり、で説明したパターンを使用します。

また、ターゲットとSyncEntitiesの間にバックレフトがありません。これは、しばしば、これらの検索スタイルを自動化する方法です。しかし、あなたはまだおおよそのものがクラスにentityKindタイプのルックアップを使用することができます:ここ

def lookup_related(se): 
    types = { 
     'commodity':CommodityTypes, 
     'foobar':FooBarTypes 
    } 
    cls = types[se.entityKind] 
    session = object_session(se) 
    return session.query(cls).filter(cls.mySyncEntity==se).all() 

もそれを行うことができミックスインだ、後方参照使用:

class HasSyncEntity(object): 
    entity_kind = None 
    "subclasses need to populate this" 

    @declared_attr 
    def uuidKey(cls): 
     return Column(String, ForeignKey("SyncEntities.uuidKey"), primary_key=True) 

    @declared_attr 
    def mySyncEntity(cls): 
     return relationship("SyncEntities", backref="_%s_collection" % cls.entity_kind) 

CommodityTypesは次のようになります。

class CommodityTypes(HasSyncEntity, Base): 
    entity_kind = "commodity" 
    # ... 

次に、このようなメソッドをSyncEntitiesに追加します。これにより、適切なバックリファレンスが検索され、完了します。

def get_related(self): 
    return getattr(self, "_%s_collection" % self.entityKind) 
関連する問題