2012-05-14 5 views
0

私の問題は次のとおりです。私はpolymorphic頂点とsqlalchemyの有向グラフ構造を持っていると私はエッジの作成の種類に依存する制限したいと思います。次のコードはグラフの構造を定義します。sqlalchemyを使用した多態グラフ構造の型依存エッジ作成

from sqlalchemy import Column, ForeignKey, Integer 
from sqlalchemy.orm import backref, relationship 
from sqlalchemy.ext.declarative import declarative_base 

Base = declarative_base() 

class Edge(Base): 
    __tablename__ = 'edge' 

    head_id = Column(Integer, ForeignKey('vertex.id'), primary_key=True) 
    tail_id = Column(Integer, ForeignKey('vertex.id'), primary_key=True) 

class Vertex(Base): 
    __tablename__ = 'vertex' 

    id = Column(Integer, primary_key=True) 
    predecessors = relationship('Vertex', 
         secondary='edge', 
         primaryjoin="Vertex.id==Edge.head_id", 
         secondaryjoin="Vertex.id==Edge.tail_id", 
         backref='successors') 
    type = Column(String(50)) 

    __mapper_args__ = { 
     'polymorphic_identity':'Vertex', 
     'polymorphic_on':type 
    } 

グラフの構築が非常に簡単

#creates two vertices with a directed edge from v1 to v2 
v1 = Vertex() 
v2 = Vertex() 
v1.successors.append(v2) # v1->v2 

ある問題は、私は依存エッジ作成タイプを制限することができますどのように」です。 など。クラスAからクラスBへのエッジは許されますが、その逆は許されません。

class A(Vertex): 
    pass 

class B(Vertex): 
    pass 

v1 = A() 
v2 = B() 
v1.successors.append(v2) #allowed 
v2.successors.append(v1) #forbidden 

答えて

1

あなたはSimple Validatorsを使用することができます。

from sqlalchemy.orm import validates 

class Vertex(Base): 
    # ... 

    @validates('successors') 
    def validate_successors(self, key, value): 
     check_value = True 
     # @todo: insert the validation logic here 
     if type(self) == B and type(value) == A: 
      check_value = False 
     assert check_value, 'Invalid Edge: not allowed to link from [{fr}] to [{to}]'.format(fr=type(self).__name__, to=type(value).__name__) 
     return value 

編集-1:検証が派生クラスに委任され追加コードサンプル:

class Vertex(Base): 
    # ... 

    def _validate_successors_impl(self, value): 
     return True 

    @validates('successors') 
    def validate_successors(self, key, value): 
     self._validate_successors_impl(value) 
     return value 

class A(Vertex): 
    __mapper_args__ = {'polymorphic_identity': 'A'} 

    def _validate_successors_impl(self, value): 
     if type(value) == B: 
      assert check_value, 'Invalid Edge: not allowed to link from [{fr}] to [{to}]'.format(fr=type(self).__name__, to=type(value).__name__) 

class B(Vertex): 
    __mapper_args__ = {'polymorphic_identity': 'B'} 
+0

どのように検証を移動します派生クラスへの論理、例えばAはそれが頂点ではなくBを受け入れないことを知っていなければならない。 – P3trus

+0

ベースに 'validator'を作成し、派生したポリモーフィズムを使ってバリデーションを委譲します。私はまもなくサンプルコードで答えを更新します... – van

関連する問題