ForeignKey使表之间的关系更加紧密
class Grade(Base): #班级表
__tablename__ = 'grade'
id = Column(Integer, primary_key=True)
gradename = Column(String(50), nullable=False)
class Person(Base):# 学生表
__tablename__ = 'stundents'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(50), nullable=False)
grade_id = Column(Integer, ForeignKey('grade.id'))
Base.metadata.create_all() #映射
如果外键关联不上,可能是因为创建的引擎默认为 :MyISAM
把它修改为 InnoDB 即可
可以在配置文件my.ini 中修改默认的引擎default-storage-engine=INNODB
表之间的关系分为一对一,一对多,多对多,根据不同的情况,存储数据时使用不同的关系。
在sqlalchemy中,仅靠外键也可以进行查询读取操作,就是有点麻烦.
简单点的方法就是定义relationship
(使用它而不使用外键是会出错的)
import random
class Person(Base):
__tablename__ = 'person'
p_id = Column(Integer,primary_key=True,autoincrement=True)
p_name = Column(String(50),nullable=False)
age = Column(Integer,default=random.randint(15,35))
class Course(Base):
__tablename__ = 'course'
c_id = Column(Integer,primary_key=True,autoincrement=True)
c_name = Column(String(50),nullable=False)
bangd = Column(Integer,ForeignKey('person.p_id'))
persons = relationship('Person',backref='courses')
# Base.metadata.drop_all();
Base.metadata.create_all();
session = sessionmaker(bind=engine)()
persons 代指Person类,relationship的第一个函数,指向一个类(Person)。
backref 表示回调,意思是从Person类 调用Course这个类使用的代指函数,也就是说 courses 代指 Course这个类。
下面就是通过Person类查询Course类中的与 zhangsan 相对应的 课程c_name
result = session.query(Person).filter_by(p_name = 'zhangsan').first()
list1=result.courses # 因为是一对多关系,所以是一个列表
for i in list1:
print(i.c_name)
上面说的backref
反向访问不是很好理解,如果不想使用 backref
,那就分别在两个类中都使用 relationship
。
# 在Course类中,通过persons代指到Person类
persons = relationship('Person')
#同样,在Person类中,也通过courses指向Coures类
courses =relationship('Course')
如果是一对多关系的表添加数据,要先添加主表的数据,接着才能添加从表的,不然会报错的。
下面的方法是通过绑定两表数据的方法一起添加数据,也就是主表从表一起添加上去。
person1 = Person(p_name='PWP')
course1 = Course(c_name='倾城之恋')
course2 = Course(c_name='杀死一只知更鸟')
course1.persons = person1
course2.persons = person1 #两本书都给一个人
session.add(course1)
session.add(course2)
session.commit()
使用append方法添加数据
person1 = Person(p_name='one')
course1 = Course(c_name='黄金时代')
course2 = Course(c_name='罪与罚')
course1.persons = person1
course2.persons = person1
person1.courses.append(course1)
person1.courses.append(course2)
session.add(person1)
session.commit()
在sqlalchemy中的一对一关系感觉好像有BUG一样
因为我在使用 uselist 进行插入数据,一对多关系的数据照样还是插了进去
像下图这样的数据,还是插入了进去,uselist = False 并没有起到作用
也许是我哪里写错的原因,欢迎各位大佬指出
class Hurman(Base):
__tablename__ = 'hurman'
h_id = Column(Integer,autoincrement=True,primary_key=True)
name = Column(String(50))
numbers = relationship('Number',uselist=False)
class Number(Base):
__tablename__ = 'number'
n_id = Column(Integer,autoincrement=True,primary_key=True)
telephone_number = Column(String(50))
hurmans = relationship('Hurman')
uid = Column(Integer,ForeignKey('hurman.h_id'))
Base.metadata.drop_all()
Base.metadata.create_all();
session = sessionmaker(bind=engine)()
hurman1 = Hurman(name='sad')
number1 = Number(telephone_number='21323131')
number2 = Number(telephone_number='11111111')
number1.hurman = hurman1
number2.hurman = hurman1
session.add(number1)
session.add(number2)
session.commit()
对了,使用uselist的同时,不能使用append 会报AttributeError: 'NoneType' object has no attribute 'append'
的错误
多对多关系,两个表建立多对多关系时,通常会新建一个表,把两个表的Id字段放进去。这时候需要用到 Table ,通过 sqlalchemy导入即可
那介于两个表之间的中间表是怎么做的呢?
如图所示:
中间表的名字Middle是我自己起的,mucic_id和user_id是显示在Middle表的字段名。中间表存放外键。
Middle = Table(
"Middle",
Base.metadata,
Column('music_id',Integer,ForeignKey('music.id')),
Column('user_id', Integer, ForeignKey('user.id'))
)
两张表,通过relationship来指定调用的关系,这里要加上secondary=Middle
,绑定到中间表。
class Music(Base):
__tablename__ = 'music'
id = Column(Integer,autoincrement=True,primary_key=True)
music_name = Column(String(50))
user = relationship('User',backref = 'music',secondary=Middle)
class User(Base):
__tablename__ = 'user'
id = Column(Integer,autoincrement=True,primary_key=True)
user_name = Column(String(50))
那我们来添加一下数据,这是使用append方法来实现的
music1 = Music(music_name='夏天的风')
music2 = Music(music_name='与我无关')
music3 = Music(music_name='MOM')
user1 = User(user_name='小李')
user2 = User(user_name='小王')
music1.user.append(user1)
music3.user.append(user1)
# 把1,3两首歌绑定到用户1
music2.user.append(user2)
music3.user.append(user2)
# 把2,3两首歌绑定给用户2
session.add(music1)
session.add(music2)
session.add(music3)
session.commit()
当然了,多对多查询数据跟一对多差不多,不过还是写下把,这样看起来字数多啊哈哈哈哈
result = session.query(User).filter_by(user_name='小王').first()
list1 = result.music
for i in list1:
print(i.music_name)