Db.session.query vs Model.query

前言

之间在使用中发现用flask-sqlalchemy 有两种查询的方法 一种是 session.query 一种是Model.query 本文通过几个编程实验探究下两者的区别。

相同之处

两种方法调用返回的对象都是query 都支持链式查询,在类似列表过滤查询条件这样的场景下,链式查询显得十分有用。

不同之处

找了一些网上的资料好像没有说明两者之间性能的区别,主要区别在用法上。Session.query 是sqlalchemy的原生功能,而model.query 是针对 model的增强,不是原生功能。具体到应用上两者的区别主要为用法不同,以下面几个场景结合输出的·sql语句为例子来体会下。
查询场景1:查询出学生的考试列表
要获得的内容格式如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
[{
“id”:,
“course_name”:,
“testpaper_title”:,
“start_time”:,
“event_time”:,
“status”:,
“test_scores”:,
},
{
“id”:,
“course_name”:,
“testpaper_title”:,
“start_time”:,
“event_time”:,
“status”:,
“test_scores”:,
}
]

涉及的表为Kt_total_score 考题总成绩以及testpaper试卷表


查询思路: 需要通过先查出考题总成绩表中,属于学生的成绩 然后拿testpaper_id 去testpaper表查试卷记录
session.query的写法

1
db.session.query(Testpaper.id,Testpaper.testpaper_title,Testpaper.start_time,Testpaper.event_time,Testpaper.status).filter(KT_total_score.stu_id == args['stu_id'])

Model.query 的写法

1
Testpaper.query.filter_by(KT_total_score.stu_id==args['stu_id']).with_entities(Testpaper.id,Testpaper.testpaper_title,Testpaper.start_time,Testpaper.event_time,Testpaper.status)

With_entities 是选择相应字段使用的函数,如果不加这个函数那么model.query会默认返回Testpaper这个Model的所有字段
输出的相应的sql语句相同均为

1
2
3
4
SELECT count(*) AS count_1 
FROM (SELECT testpaper.id AS testpaper_id, testpaper.testpaper_title AS testpaper_testpaper_title, testpaper.start_time AS testpaper_start_time, testpaper.event_time AS testpaper_event_time, testpaper.status AS testpaper_status
FROM testpaper, kt_total_score
WHERE kt_total_score.stu_id = %s) AS anon_1

在这个场景下,session.query 的代码更加简短,可读性也更加好。
再看另外一个场景,查询一个学生的所有历史考试成绩。也就是以学生id去查询考试总成绩表中的记录
查询场景2:查询一个学生的所有历史考试成绩
session.query的写法:

1
db.session.query(KT_TOTAL_SCORE).filter(KT_total_score.stu_id =='2')

Model.query 的写法:

1
KT_TOTAL_SCORE.query.filter_by(stu_id=='2')

filter_by 是model.query 特有的对单表过滤的进一步简化,使得在输入的时候不需要带上model的名字直接给字段名就可以
可以看到 在这种情况下 model.query 写起来要更加方便。

总结

这两个方法功能上相同,基本差别就是在用法上,model.query 在单模型查找上明显比session.querry 写着要简洁。

参考资料

  1. SQLAlchemy 使用简略

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!