0

我正在设计一个图形数据库结构。一个节点可以是一个人、一个部门等。这就是我添加 nodeType 的原因。节点之间的关系也可以是多种类型。从下面的代码中,r1 和 r2 被插入到数据库中。当我阅读数据库时,我看到 null null null。这是为什么 ?我希望看到与.id 字段相关的值(例如 n1.id、rt1.id、n2.id)

from sqlalchemy import MetaData, Table, Column, Integer, ForeignKey, \
    create_engine, String
from sqlalchemy.orm import mapper, relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///dir_graph.sqlite', echo=True)

Base = declarative_base()
Session = sessionmaker(bind=engine)
session = Session()

class NodeType(Base):
    __tablename__ = 'nodetype'
    id      = Column(Integer, primary_key=True)
    name    = Column(String(20), unique=True)
    nodes   = relationship('Node', backref='nodetype')

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "Nodetype: %s" % (self.name)


class Node(Base):
    __tablename__ = 'node'

    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    type_id = Column(Integer,
                        ForeignKey('nodetype.id')) 

    def __init__(self, _name, _type_id):
        self.name = _name
        self.type_id = _type_id

class Relation(Base):
    __tablename__ = 'relation'

    id      = Column(Integer, primary_key=True)
    name    = Column(String(20), unique=True)
    type_id = Column(Integer,
                        ForeignKey('relationtype.id')) 

    from_id = Column(Integer,
                        ForeignKey('node.id'))

    to_id = Column(Integer,
                        ForeignKey('node.id'))


    def __init__(self, _fromNode, _type_id, _toNode):
            self.from_id = _fromNode
            self.type_id =  _type_id
            self.to_id   = _toNode

class RelationType(Base):
    __tablename__ = 'relationtype'

    id             = Column(Integer, primary_key=True)
    name           = Column(String(20), unique=True)
    description    = Column(String(30), unique=True)

    relations      = relationship('Relation', backref='relationtype')

    def __init__(self, _name):  
        self.name = _name

    def description(self, _description):
        self.description = _description  
Base.metadata.create_all(engine)

nt1 = NodeType('nt1')
nt2 = NodeType('nt2')

n1 = Node('n1type1', 1)
n2 = Node('n2type1', 1)
n3 = Node('n3type1', 1)
n4 = Node('n4type2', 2)
n5 = Node('n5type2', 2)

rt1 = RelationType('rt1')
rt2 = RelationType('rt2')
rt3 = RelationType('rt3')

r1 = Relation(n1.id,rt1.id,n2.id)
r2 = Relation(n3.id,rt2.id,n5.id)

session.add_all([nt1,nt2,n1,n2,n3,n4,n5,rt1,rt2,rt3,r1,r2])
session.commit()

其他关于代码改进的评论也值得赞赏。

4

1 回答 1

2

您的代码的问题是您在将节点插入数据库之前尝试使用 Node.id 属性。在您调用session.flush()or之前session.commit(),新创建的对象没有 ID,并且不能,因为它是生成 ID 的数据库引擎。

所以 SQLAlchemy 这样做的方法是定义Relation对象和Node对象之间的关系,并分配对象Relation.__init__而不是分配 id。像这样:

from sqlalchemy import MetaData, Table, Column, Integer, ForeignKey, \
    create_engine, String
from sqlalchemy.orm import mapper, relationship, sessionmaker
from sqlalchemy.ext.declarative import declarative_base

engine = create_engine('sqlite:///dir_graph.sqlite', echo=True)

Base = declarative_base()
Session = sessionmaker(bind=engine)
session = Session()


class NodeType(Base):
    __tablename__ = 'nodetype'
    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    nodes = relationship('Node', backref='nodetype')

    def __init__(self, name):
        self.name = name

    def __repr__(self):
        return "Nodetype: %s" % self.name


class Node(Base):
    __tablename__ = 'node'

    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    type_id = Column(Integer,
                     ForeignKey('nodetype.id'))


    def __init__(self, _name, _type_id):
        self.name = _name
        self.type_id = _type_id


class Relation(Base):
    __tablename__ = 'relation'

    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    type_id = Column(Integer,
                     ForeignKey('relationtype.id'))

    from_id = Column(Integer,
                     ForeignKey('node.id'))

    to_id = Column(Integer,
                   ForeignKey('node.id'))

    from_node = relationship(Node, primaryjoin=Node.id == from_id)
    to_node = relationship(Node, primaryjoin=Node.id == to_id)

    def __init__(self, _fromNode, _type_id, _toNode):
        self.from_node = _fromNode
        self.type_id = _type_id
        self.to_node = _toNode


class RelationType(Base):
    __tablename__ = 'relationtype'

    id = Column(Integer, primary_key=True)
    name = Column(String(20), unique=True)
    description = Column(String(30), unique=True)

    relations = relationship('Relation', backref='relationtype')

    def __init__(self, _name):
        self.name = _name

    def description(self, _description):
        self.description = _description


Base.metadata.create_all(engine)

nt1 = NodeType('nt1')
nt2 = NodeType('nt2')

n1 = Node('n1type1', 1)
n2 = Node('n2type1', 1)
n3 = Node('n3type1', 1)
n4 = Node('n4type2', 2)
n5 = Node('n5type2', 2)

rt1 = RelationType('rt1')
rt2 = RelationType('rt2')
rt3 = RelationType('rt3')

r1 = Relation(n1, rt1.id, n2)
r2 = Relation(n3, rt2.id, n5)

session.add_all([nt1, nt2, n1, n2, n3, n4, n5, rt1, rt2, rt3, r1, r2])
session.commit()
于 2013-02-27T18:14:26.743 回答