Flask-SQLalchemy之relationship学习

先来看下面这个一对多的数据表(一门课程可以多个学生选择)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Student(db.Model):
__tablename__ = 'students'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
class_id = db.Column(db.Integer, db.ForeignKey('classes.id'))
def __repr__(self):
return '<Student: %r>' % self.name

class Class(db.Model):
__tablename__ = 'classes'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(64))
def __repr__(self):
return '<Class: %r>' % self.name

上面代码建立了两个数据表“students”和“classes”且都有两列属性id和name。其中“students”表多了一个外键class_id关联的是classes表中的id列。代表students选择的class。然后我们插入一些数据,使得数据表如下所示:
屏幕快照 2017-12-27 上午12.26.47
students
屏幕快照 2017-12-27 上午12.19.05
class
可以看到,我们插入了3个student信息和2个class信息。根据class_id我们可以看到jack选择的是class2,其余两个人选择的是课程1。
那么现在问题来了,如果你没有看到上图,现在求jack选的哪门课,该怎么选?
很显然,我们只需要知道jack的class_id即可。体现在SQLalchemy中查询如下:
屏幕快照 2017-12-27 上午1.03.00
可以看到,这么查询起来比较麻烦,而relationship函数则可以让我们很方便的完成类似上面的查询。例如我们现在想求所有选择class1的student。
我们先把下面一行代码加到Class里面:

1
students = db.relationship('Student', backref='classes',lazy='select')

现在,我们只需要像下面调用查询即可:
屏幕快照 2017-12-27 上午1.34.18
可以看到通过students属性,我们就可以直接查询到选择class1课程的student。
同样,我们可以用下面的语句来查询jack选择了哪个课程。
屏幕快照 2017-12-27 上午1.40.26
这里要注意的是,如果上面的students属性没有这个反向查询的参数backref=‘classes’,则这个查询无法完成。
至此relationship函数的作用已经清楚,下面学习一下这个函数的lazy参数。
lazy参数决定了SQLAlchemy什么时候从数据库中加载数据。常用的有三个值:
select,访问到属性的时候,就会全部加载该属性的数据。
dynamic,访问属性的时候,并没有在内存中加载数据,而是返回一个query对象,需要执行相应方法才可以获取对象
joined,对关联的两个表进行join操作,从而获取到所有相关的对象
首先,我们relationship函数的lazy参数默认为select,我们来看下class.students的查询结果:
屏幕快照 2017-12-28 上午12.37.37
可以看到,当参数为select时候,直接返回了结果列表。也就是上面说的访问到属性后,直接加载该属性的数据。
然后我们把参数值改为dynamic:

1
students = db.relationship('Student', backref='classes',lazy='dynamic')

再来看一下结果:
屏幕快照 2017-12-28 上午12.46.34
这时可以看到,c1.students返回的是一个query对象,我们可以在它上面再次进行查询,比如all()。需要注意的时候,lazy=”dynamic”只可以用在一对多和多对多关系中,不可以用在一对一和多对一种,因为如果返回结果只有一个,也就无需延迟加载数据了。

参考资料:
SQLalchemy relationship之lazy属性 学习笔记
flask-sqlalchemy中 backref lazy的参数实例解释和选择
遇到一个问题,请各位给讲解一下sqlalchemy中的backref?

坚持原创技术分享,您的支持将鼓励我继续创作!