数据库中的多对多关系及其在Flask Web开发中的实现

翻译 2018年04月15日 20:03:01

一对多关系、多对一关系和一对一关系至少都有一侧是单个实体,所以记录之间的联系通过外键实现,让外键指向这个实体。但是,你要如何实现两侧都是“多”的关系呢?

下面以一个典型的多对多关系为例,即一个记录学生和他们所选课程的数据库。很显然,你不能在学生表中加入一个指向课程的外键,因为一个学生可以选择多个课程,一个外键不够用。同样,你也不能在课程表中加入一个指向学生的外键,因为一个课程有多个学生选择。两侧都需要一组外键。

这种问题的解决方法是添加第三张表,这个表称为关联表。现在,多对多关系可以分解成原表和关联表之间的两个一对多关系。下图描绘了学生和课程之间的多对多关系。
多对多关系示例
这个例子中的关联表是 registrations ,表中的每一行都表示一个学生注册的一个课程。查询多对多关系要分成两步。若想知道某位学生选择了哪些课程,你要先从学生和注册之间的一对多关系开始,获取这位学生在 registrations 表中的所有记录,然后再按照多到一的方向遍历课程和注册之间的一对多关系,找到这位学生在 registrations 表中各记录所对应的课程。同样,若想找到选择了某门课程的所有学生,你要先从课程表中开始,获取其在 registrations 表中的记录,再获取这些记录联接的学生。

通过遍历两个关系来获取查询结果的做法听起来有难度,不过像前例这种简单关系,SQLAlchemy 就可以完成大部分操作。上图中的多对多关系使用的代码表示如下:

registrations = db.Table('registrations',
    db.Column('student_id',db.Integer,db.ForeignKey('students.id')),
    db.Column('class_id', db.Integer, db.ForeignKey('classes.id'))
)

class Student(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String)
    classes = db.relationship('Class',
        secondary=registrations,
        backref=db.backref('students', lazy='dynamic'),
        lazy='dynamic')

class Class(db.Model):
    id = db.Column(db.Integer, primary_key = True)
    name = db.Column(db.String)

多对多关系仍使用定义一对多关系的 db.relationship() 方法进行定义,但在多对多关系中,必须把 secondary 参数设为关联表。多对多关系可以在任何一个类中定义, backref 参数会处理好关系的另一侧。关联表就是一个简单的表,不是模型,SQLAlchemy 会自动接管这个表。
classes 关系使用列表语义,这样处理多对多关系特别简单。假设学生是 s ,课程是 c ,学生注册课程的代码为:


>>> s.classes.append(c)
>>> db.session.add(s)

列出学生 s 注册的课程以及注册了课程 c 的学生也很简单:

>>> s.classes.all()
>>> c.students.all()

Class 模型中的 students 关系由参数 db.backref() 定义。注意,这个关系中还指定了 lazy= ‘dynamic’ 参数,所以关系两侧返回的查询都可接受额外的过滤器。
如果后来学生 s 决定不选课程 c 了,那么可使用下面的代码更新数据库:

>>> s.classes.remove(c)

—-摘自《Flask Web开发:基于Python的Web应用开发实践》

Flask 数据库高级多对多关系

之前介绍了多对多关系:http://blog.csdn.net/ying847782627/article/details/51333090         在之前介绍的多对多关系中,关联表就是一个简...
  • ying847782627
  • ying847782627
  • 2016-05-07 19:43:04
  • 2968

Flask 数据库多对多关系

数据库使用关系建立记录之间的联系。其中,一对多关系是最常用的关系类型,它把一个记录和一组相关的记录联系在一起。实现这种关系时,要在“多”这一侧加入一个外键,指向“一”这一侧联接的记录。大部分的其他关系...
  • ying847782627
  • ying847782627
  • 2016-05-06 17:05:58
  • 5341

Flask-多对多关系

看了第四遍Miguel Grinberg写的《Flask Web》一书,前面部分都非常顺利,但到了关注者这一章,被多对多关系卡住了。在写本篇博客时我脑子里还是一团浆糊,边写边想吧。在说多对多关系之前,...
  • PythonKidDz
  • PythonKidDz
  • 2017-03-09 17:04:40
  • 1425

数据库多对多关系

一般我们用三张表来描述多对多的关系。例子:多个分类,每个分类有多个商品。另外每个商品在不同的分类。以下例子不太恰当,自己瞎举得,知道意思就好类:水果 A类 B类商品:A果,A菜,B果,B菜,我们创建数...
  • jhkj_5154
  • jhkj_5154
  • 2018-02-27 23:59:06
  • 111

Flask 数据库多对多自引用关系

上篇介绍的多对多关系是两个模型是之间的多对多关系,关联表联接的是两个明确的实体,还有些情况下只有一个模型,与自己之间存在多对多关系。比如用户之间的关注。表示用户关注其他用户时,只有用户一个实体,没有 ...
  • ying847782627
  • ying847782627
  • 2016-05-09 20:04:41
  • 2180

请教数据库如何建立多对多关系

请教数据库如何建立多对多关系(最好以mysql为例) 请问数据库怎么建立多对多关系(最好以mysql为例) 我建立了两张表: create table...
  • zhjmyx
  • zhjmyx
  • 2016-05-31 13:48:31
  • 2361

sqlalchemy中多对多的关系

一、sqlalchemy数据库中多对多的关系,主要有下面三个步骤 定义一个中间表保存两个表的主键 定义多对多关系的两个表的模型 给每个模型都添加一个访问对方的属性注意在relationship中指定中...
  • kuangshp128
  • kuangshp128
  • 2017-03-12 15:23:16
  • 1286

数据库中多对多的关系设计

数据库设计多对多关系的几种形态   前言:多对多关系至少需要3个表,我们把一个表叫做主表,一个叫做关系表,另外一个叫做字典表或者副表(字典表是纪录比较少,而且基本稳定的,例如:版块名称;副表是内容比较...
  • xianda9133
  • xianda9133
  • 2016-01-27 23:16:56
  • 1718

mysql多对多关系的构建

translate from http://www.phpknowhow.com/mysql/many-to-many-relationships/ 在这篇文章中,我们要看看它有一个特殊的存储机...
  • shruby
  • shruby
  • 2014-12-05 22:03:07
  • 715

数据库中表关系(一对多,多对多,一对一)

一对多关系 一对多关系是最普通的一种关系。在这种关系中,A 表中的一行可以匹配 B 表中的多行,但是 B 表中的一行只能匹配 A 表中的一行。例如,publishers 和 titles 表之间...
  • curry_du
  • curry_du
  • 2016-03-08 11:41:23
  • 12288
收藏助手
不良信息举报
您举报文章:数据库中的多对多关系及其在Flask Web开发中的实现
举报原因:
原因补充:

(最多只允许输入30个字)