Django学习笔记:F对象、Q对象、聚合分组查询和原生SQL
F对象
在高并发的情景下,若要对一个文章的点赞量进行增量更新,我们就不可以再程序里先读后写了,因为多个线程在短时间内读到的可能是同一时刻的数据,在程序中做增量更新后保存到数据库可能会导致重复覆盖,解决方法有两个:在java中我习惯用锁机制和事务来控制。也可以直接写成mysql语句,在一条语句中做更新操作,这得益于mysql自己内部的锁机制可以对线程的数据更新加锁。
了解到这一点后,我们可以在django中也采用类似的机制来实现,由于django的orm机制本质上是对mysql语法的进一步封装,想要达到加锁的效果就直接利用mysql的锁即可。这里我们需要用到F对象,F对象是对字段的抽象标记。
记得先导入D对象再使用
article.like=F('like')+1其实没有在读取数据也没有再修改数据,知识对字段做了一个提前的说明,直到执行save(),框架就会自动生产sql语句:update article set like =like+1 where id =xxx 。利用的是mysql自带的锁,我们就不必在业务层加锁了。
F属性是对字段的抽象标记,很多情况下都可以来简化代码的书写:如果我们要选出收藏量大于点赞数的文章的列表:
相当于sql中的:select * from artice where collect >like。
Q对象
Q对象是用来实现或、非条件的对象,在django中,条件并列传入框架中默认为&关系,也就是“并且”的关系。要实现|以及~则需要再引进Q对象,当然Q对象也可以实现“且”的作用
Q(cdt1)|Q(cdt2) :条件一或者条件二名字
Q(cdt1)&Q(cdt2): 条件一和条件二同时满足
Q(cdt1)&~Q(cdt2):条件一满足并且条件二不满足
~Q(cdt1)&~Q(cdt2) :条件一和条件二都不满足
Q对象的位置和F对象同级:
用途如下:

聚合查询
整表聚合:

整表聚合返回的是字典,这种返回形式更加自由

分组聚合:


这里一开始不好理解,通过简单的代码来习惯这种用法:

values('c1', 'c2'...)获取表的每一行数据的内容,每一行数据的表示以下格式:
{c1:c1val,c2:c2val,...}。
获取到指定字段到所有数据后,就可以利用annotate对数据根据指定的字段进行分组,以聚合函数返回值作为该组的值。可以表示为以下格式:
{c1:c1val,c2:c2val,...,名:聚合函数(作用字段),...} 分组体现在对于合并了相同的cn:cnval。而聚合函数得到的键值对,类似于对该组的追加的注解,所以分组聚合的函数叫做annotate,某种程度来看挺合理的。

在写orm的内容的时候,我觉得单表简单查询上orm很有意义,但是在复杂查询的时候,可能是sql更有优势了,对此,django也允许直接使用sql来与数据库交互。

注意,拼接参数层面已经包含sql注入的检查了。
多表查询方面,这个文章说的不错!