系列文章目录 第一章 django安装与介绍
第二章 django基础使用
【django框架|django框架——模型层(下)】第三章 路由层
第四章 虚拟环境、django版本区别、视图层
第五章 模板层
第六章 模型层(上)
第七章 模型层(下)
文章目录
- 系列文章目录
- 一、聚合查询
-
- 1.Avg
- 2.Sum
- 3.Max
- 4.Min
- 5.Count
- 二、分组查询
- 三、F查询
- 四、Q查询
- 五、查询优化
-
- 1.only
- 2.defer
- 3.select_related
- 4.prefetch_related
- 六、事务操作
- 七、ORM执行原生SQL
-
- 1.方式1
- 2.方式2
- 八、多对多关系三种创建方式
-
- 1.全自动(常见)
- 2.全手动(使用频率最低)
- 3.半自动(常见)
一、聚合查询 相当于mysql的聚合函数,使用聚合函数需要搭配aggregate,每个聚合函数需要去django.db.models模块下导入
from django.db.models import Count,Avg,Sum,Min,Max
1.Avg 求平均值
eg:
models.User.objects.aggregate(Avg('money'))
2.Sum 求和
eg:
models.User.objects.aggregate(Sum('money'))
3.Max 求最大
eg:
models.User.objects.aggregate(Max('money'))
4.Min 求最小
eg:
models.User.objects.aggregate(Min('money'))
5.Count 对记录进行计数
eg:
models.User.objects.aggregate(Count('uid'))
二、分组查询 分组查询就是对查询结果按照一定条件来划分结果,类似mysql中的group by
ORM执行分组操作 如果报错 可能需要去mysql配置文件中修改sql_mode
移除only_full_group_by
将对象句点符调用annotate方法就是按照数据对象进行分组,对象可以是数据对象也可以是一张表
class Press(models.Model):
pid = models.AutoField(primary_key=True)
pname = models.CharField(max_length=20)
address = models.CharField(max_length=20)class Book(models.Model):
bid = models.AutoField(primary_key=True)
bname = models.CharField(max_length=20)
price = models.DecimalField(max_digits=8, decimal_places=2)
sell = models.IntegerField()
press = models.ForeignKey(Press) # 查询每个作者的书籍数量 表分组查询
res = models.User.objects.annotate(book_num=Count("book")).values("username", "book_num")
print(res)# 查询每个作者的书籍数量 字段分组查询
res1 = models.Book.objects.values("user__uid").annotate(book_num = Count("user__uid")).values("user__username", "book_num")
print(res1)
三、F查询 当查询条件的左右两表的数据都需要表中的数据 可以使用F查询
F查询时需要导入模块才能使用的:
from django.db.models import F
class Book(models.Model):
bid = models.AutoField(primary_key=True)
bname = models.CharField(max_length=20)
price = models.DecimalField(max_digits=8, decimal_places=2)
sell = models.IntegerField()# 查询库存比销量大400的数据
from django.db.models import F
res = models.Book.objects.filter(quantity__gt = F('sell') + 400).values("bname", "sell", "quantity")
print(res)
当需要修改字符字段值时,如果是想在原有的基础上添加新的前后缀需要一下俩个方法
from django.db.models.functions import Concat
from django.db.models import Valueres = models.Book.objects.update(bname=Concat(F('bname'), Value('爆款')))
四、Q查询 当我们需要逻辑运算符的时候需要使用Q查询,Q函数中的条件是可以用字符串型变量来指定字段
Q函数之间使用,隔开为且的逻辑
Q函数之间使用 | 隔开为或的逻辑
以及使用~来进行取反
首先要导入Q
from django.db.models import Q
# 查询价格大于1200且销售量大于12的书籍
from django.db.models import Q
res = models.Book.objects.filter(Q(price__gt=1200), Q(sell__gt=12)).values("bname",'sell', 'price')
print(res)# 查询价格大于1200或销售量大于12的书籍
from django.db.models import Q
res1 = models.Book.objects.filter(Q(price__gt=1200)| Q(sell__gt=12)).values("bname", 'sell', 'price')
print(res1) # 查询价格不大于1200或销售量不大于12的书籍
res1 = models.Book.objects.filter(~Q(price__gt=1200)| ~Q(sell__gt=12)).values("bname", 'sell', 'price')
print(res1)
五、查询优化 对于查询优化,主要目的是为了减轻数据库的负担,因为访问量过大时容易导致数据库处理不过来,甚至可能卡死
1.orm查询默认都是惰性查询
光编写orm语句并不会直接指向SQL语句 只有后续的代码用到了才会执行
2.orm查询默认自带分页功能
limit 为21
1.only
res = models.Book.objects.only('bname', 'price')
此时因为没有使用查询的内容,不会出现rom操作mysql的情况
文章图片
res = models.Book.objects.only('bname', 'price')
print(res)
此时有操作调用,所以rom会操作数据库获取数据
文章图片
only会产生对象结果集,数据对象点only内出现的字段不会再操作数据库查询,不再only里的会再次操作数据库获得数据
res = models.Book.objects.only('bname', 'price')
for i in res:
print(i.bid)
print(i.bname)
文章图片
2.defer defer与only刚好相反 对defer内出现的字段会操作数据库
如果点击了defer内没有的字段也可以获取到数据且每次都不会走数据库查询
3.select_related select_related括号内只能传一对一和一对多字段
效果是内部直接连接表(inner join) 然后将连接之后的表中所有的数据全部封装到数据对象中
后续对象通过正反向查询跨表 内部不会再走数据库查询
eg:
models.Book.objects.select_related('press')
for obj in res:
print(obj.bname)
print(obj.press.pname)
print(obj.press.address)
4.prefetch_related prefetch_related对于多对多字段和反向外键关系
效果是内部直接连接表(inner join) 然后将连接之后的表中所有的数据全部封装到数据对象中
后续对象通过正反向查询跨表 内部不会再走数据库查询
eg:
models.Book.objects.prefetch_related('press')
for obj in res:
print(obj.bname)
print(obj.press.pname)
print(obj.press.address)
六、事务操作
from django.db import transaction
try:
with transaction.atomic():
pass # 此处书写事务代码将会提交
except Exception:
pass # 到这里会回滚
七、ORM执行原生SQL 1.方式1
from django.db import connection, connections
cursor = connection.cursor()
cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
cursor.fetchone()
2.方式2
models.UserInfo.objects.extra(
select={'newid':'select count(1) from app01_usertype where id>%s'},
select_params=[1,],
where = ['age>%s'],
params=[18,],
order_by=['-age'],
tables=['app01_usertype']
)
八、多对多关系三种创建方式 1.全自动(常见) orm自动创建第三张表 但是无法扩展第三张表的字段
authors = models.ManyToManyField(to=‘Author’)
2.全手动(使用频率最低) 优势在于第三张表完全自定义扩展性高 劣势在于无法使用外键方法和正反向查询
class Book(models.Model):
title = models.CharField(max_length=32)
class Author(models.Model):
name = models.CharField(max_length=32)
class Book2Author(models.Model):
book_id = models.ForeignKey(to='Book')
author_id = models.ForeignKey(to='Author')
3.半自动(常见) 正反向还可以使用 并且第三张表可以扩展 唯一的缺陷是不能用
add\set\remove\clear四个方法
class Book(models.Model):
title = models.CharField(max_length=32)
authors = models.ManyToManyField(
to='Author',
through='Book2Author',# 指定表
through_fields=('book','author')# 指定字段
)
class Author(models.Model):
name = models.CharField(max_length=32)
'''多对多建在任意一方都可以 如果建在作者表 字段顺序互换即可'''
books = models.ManyToManyField(
to='Author',
through='Book2Author',# 指定表
through_fields=('author','book')# 指定字段
)
class Book2Author(models.Model):
book = models.ForeignKey(to='Book')
author = models.ForeignKey(to='Author')
推荐阅读
- django框架|django框架——模型层(上)
- django框架|django框架——ajax
- django框架|django框架——路由层
- web框架|django框架——模板层
- web框架|django框架——django基础使用
- web框架|django框架——虚拟环境、django版本区别、视图层
- django框架|django——版本问题、启动问题、安装、基础使用、应用app、django主要文件介绍
- 网络编程|网络编程——socket套接字、黏包
- python——用Turtle画画写名字