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

您可以使用简单验证器

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 回答