Flask——SQLAlchemy外键以及四种约束,一对多,一对一,多对多关系详解

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

外键的四种约束

  • RESTRICT :默认约束类型,主表数据被删除会报错,阻止其删除
  • NO ACTION :同RESTRICT一样
  • CASCADE :级联删除,主表数据删除,从表相对应的数据随之被删除
  • SET NULL :主表数据被删除,从表与之对应的数据变为NULL
    在这里插入图片描述

一对多关系

表之间的关系分为一对一,一对多,多对多,根据不同的情况,存储数据时使用不同的关系。
在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)

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值