使用sqlalchemy

时间:2015-05-23 20:02:01

标签: python mysql sqlalchemy

class A(Base):
     __tablename__ = 'a'

    id = Column(Integer, primary_key=True)
    name = Column(String(1000))

class B(Base):
    __tablename__ = 'b'

    id = Column(Integer, primary_key=True)
    name = Column(String(1000))

class C(Base):
    __tablename__ = 'c'

    id = Column(Integer, primary_key=True)
    b_id = Column(Integer, ForeignKey('b.id'))
    name = Column(String(1000))
    a_id = Column(Integer, ForeignKey('a.id'))

    b = relationship('B', backref=backref('cb'), foreign_keys = b_id)
    a = relationship('A', backref=backref('ca'), foreign_keys = a_id)

connect = engine.connect()
Base.metadata.create_all(bind=engine)

我创建了一些类来创建表并使用sqlalchemy将数据添加到MySQL数据库。我现在面临的问题如下。

如果我想在表c中添加一个条目,我需要的就是这样的代码。

c_ent = C(name = 'c1')
a1 = A(name = 'a1')
b1 = B(name = 'b1')

a1.ca = [c_ent]
b1.cb = [c_ent]

list1 = [a1, b1]

sess = create_session(name)
for i in list1:
    sess.add(i)

sess.commit()
sess.close()

这一切都按我需要的方式工作,c条目中b_id和a_id的外键与a和b中相应id的外键匹配。

但是,假设在提交到数据库并关闭会话后,我现在决定将另一个条目添加到c,' c2'。我希望此条目与表a和b具有相同的关系作为我的第一个(因此a_id和b_id与名为' c1'的条目相同)。但是,如果我使用类似于第一个条目的代码,sqlalchemy将在表a和b中创建重复的条目,其名称为' a1'和' b1' ID号为2而不是1.然后,我在表c中的条目将具有正确的ID号,但它们将链接到重复的条目。

我希望能够向c添加一个条目,但是我选择多次并将其与表a和b相关联,而不是每次都在a和b中创建新条目。如何避免这种冗余?

1 个答案:

答案 0 :(得分:1)

尝试这样做:

c2 = C(name='c2')
c2.a = a1
c2.b = b1

sess = create_session(name)
sess.add(c2)
sess.commit()
sess.close()

使用sqlite的完整代码:

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


Base = declarative_base()


class A(Base):
    __tablename__ = 'a'

    id = Column(Integer, primary_key=True)
    name = Column(String(1000))


class B(Base):
    __tablename__ = 'b'

    id = Column(Integer, primary_key=True)
    name = Column(String(1000))


class C(Base):
    __tablename__ = 'c'

    id = Column(Integer, primary_key=True)
    b_id = Column(Integer, ForeignKey('b.id'))
    name = Column(String(1000))
    a_id = Column(Integer, ForeignKey('a.id'))

    b = relationship('B', backref=backref('cb'), foreign_keys=b_id)
    a = relationship('A', backref=backref('ca'), foreign_keys=a_id)

engine = create_engine('sqlite:////tmp/temp.db')

connect = engine.connect()
Base.metadata.create_all(bind=engine)

Session = sessionmaker(bind=engine)
sess = Session()

c_ent = C(name='c1')
a1 = A(name='a1')
b1 = B(name='b1')

a1.ca = [c_ent]
b1.cb = [c_ent]

list1 = [a1, b1]

for i in list1:
    sess.add(i)
sess.commit()

c2 = C(name='c2')
c2.a = a1
c2.b = b1
sess.add(c2)
sess.commit()

sess.close()

执行后:

$ sqlite3 /tmp/temp.db 
SQLite version 3.8.2 2013-12-06 14:53:30
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> SELECT * FROM c;
1|1|c1|1
2|1|c2|1
sqlite> SELECT * FROM a;
1|a1
sqlite> SELECT * FROM b;
1|b1

如您所见,没有重复的数据。表a中只有一个条目,表b中只有一个条目。