0

私の問題は次のとおりです。多形頂点を持つ 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
4

1 に答える 1

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

edit-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'}
于 2012-05-14T10:35:21.927 に答える