SQLAlchemy —— 表关系

Flask 学习笔记

一、一对多


        表之间的关系存在三种:一对一、一对多、多对多。而 SQLAlchemy 中的 ORM 也可以模拟这三种关系。因为一对一其实在 SQLAlchemy 中底层是通过一对多的方式模拟的。


1.1、一对多

        如上 user2 表中的一条数据与 article2 表的多条数据存在关联。为了方便查询我们可以使用 relationship 在创建类时使两表建立关联。

	class Article2(Base):
	    __tablename__ = 'article2'
	
	    id = Column(Integer, primary_key=True, autoincrement=True)
	    title = Column(String(50))
	    content = Column(Text, nullable=False)
	    uid = Column(Integer, ForeignKey('user2.id', ondelete='SET NULL'))
	
	    # 建立关联
	    author = relationship("User2")
	
	    def __str__(self):
	        return f"{self.title}   {self.content}   {self.uid}"
	
	
	class User2(Base):
	    __tablename__ = 'user2'
	
	    id = Column(Integer, primary_key=True, autoincrement=True)
	    username = Column(String(50), nullable=False)
	
	    # 建立关联
	    articles = relationship("Article2")
	
	    def __str__(self):
	        return f"{self.id}   {self.username}"
	
	
	# Base.metadata.drop_all()
	Base.metadata.create_all()
	
	session = sessionmaker(bind=engine)()

也可以在一个类中创建一条:

    # 反向访问的属性(这是在 User2 类中设置的)
    # author 变量名可以随便取, 访问时写对就行
    articles = relationship("Article2", backref='author')

数据
在这里插入图片描述
在这里插入图片描述

1.2、几个查询示例:

	# 查询 article2 表中第一条记录所对应的 user 表中的用户名
	res = session.query(Article2).first()
	# 这里的 author 是在 User2 类中定义的, 返回的是 外键所对应的记录
	print(res)
	print(res.author)
	
	
	# 查询 bb 所对应的用户名
	res = session.query(Article2).filter(Article2.title == 'bb')
	# print(res)
	for i in res:
	    print(i)
	
	
	# 查询 1 所对应的 article2 表中的记录
	res = session.query(User2).filter(User2.username == 'a')
	for i in res:
	    print(i)
	    for data in i.articles:
	        print(data)



1.3、数据添加:

	# 添加单条数据
	user = User2(username='张三')
	article = Article2(title='PHP', content='xxxx')
	
	article.author = user			# 该句用来为父表添加数据
	session.add(article)			# 虽然看起来只有 article2 表进行了添加操作, 实际上两个表都添加了数据
	session.commit()
	
	
	# 添加多条数据
	user = session.query(User2).first()
	article1 = Article2(title='JS', content='xxxx1')
	article2 = Article2(title='Java', content='xxxx2')
	
	article1.author = user
	article2.author = user
	session.add(article1)
	session.add(article2)
	session.commit()



二、一对一


        一对一其实就是一对多的特殊情况。从以上的一对多例子中不难发现,一对多是指 user2 表中的一条记录对应 article2 表中的多条数据。因此,要将一对多转换成一对一,只要设置一个 User2 对象对应一个 Article2 对象即可。通过设置 uselist=False 实现。

    articles = relationship("Article2", backref='author', uselist=False)

应用举例:

        现某网站要存储 1000 个用户的信息,收集到的用户信息大致分为 20 项,其中 6 项为常用项(如 用户名、密码等),14 项为非常用项(如 性别、年龄等)。因此,为了方便查询管理分别用两个表存储这些数据,那么这两个表中的数据就是一对一的关系。




三、对多对


3.1、创建

        多对多需要一个中间表来作为连接,同理在 sqlalchemy 中的 orm 也需要一个中间表。假如现在有一个 Teacher 和一个 Classes 表,即老师和班级,一个老师可以教多个班级,一个班级有多个老师,是一种典型的多对多的关系,那么通过 sqlalchemyORM 的实现方式。要创建一个多对多的关系表,首先需要一个中间表,通过Table来创建一个中间表。

Table 的几个参数:

  1. 第一个参数:代表的是中间表的表名;

  2. 第二个参数:是Base的元类;

  3. 第三个和第四个参数:是要连接的两个表(用到 Column 其中也有三个参数)。
    (1) 第1个参数:表示的是连接表的外键名
    (2) 第2个参数:表示这个外键的类型
    (3) 第3个参数:表示要外键的表名和字段

	from sqlalchemy import Table

	# 创建一个中间表, 用于存储两个表的外键(需要导入 Table)
	association_table = Table(
	    'teacher_classes',
	    Base.metadata,
	  	Column('teacher_id',Integer,ForeignKey('teacher.id')),
	  	Column('classes_id',Integer,ForeignKey('classes.id'))
	  )
	
	
	class Teacher(Base):
	    __tablename__ = 'teacher'
	    
	    id = Column(Integer, primary_key=True)
	    tno = Column(String(10))
	    name = Column(String(50))
	    age = Column(Integer)
	    
	    # 通过 secondary 属性与中间表建立联系
	    classes = relationship('Classes', secondary=association_table, backref='teachers')
	
	
	 class Classes(Base):
	    __tablename__ = 'classes'
	    
	    id = Column(Integer, primary_key=True)
	    cno = Column(String(10))
	    name = Column(String(50))



3.2、添加数据(顺便介绍一种给外键添加数据的方法 append()

	teacher1 = Teacher(name='MathTC')
	teacher2 = Teacher(name='EnglishTC')
	class1 = Classes(name='c1')
	class2 = Classes(name='c2')
	
	teacher1.classes.append(class1)
	teacher1.classes.append(class2)
	session.add(teacher1)
	class2.teachers.append(teacher1)
	class2.teachers.append(teacher2)
	session.add(class2)
	
	session.commit()



3.3、查询测试

	# 老师对应的班级
	teacher = session.query(Teacher).first()
	print("\n老师对应的班级\n", teacher)
	for i in teacher.classes:
	    print(i)
	
	
	# 班级对应的老师
	classes = session.query(Classes).first()
	print("\n班级对应的老师\n", classes)
	for i in classes.teachers:
	    print(i)
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值