django框架|django框架——模型层(下)

系列文章目录 第一章 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的情况
django框架|django框架——模型层(下)
文章图片

res = models.Book.objects.only('bname', 'price') print(res)

此时有操作调用,所以rom会操作数据库获取数据
django框架|django框架——模型层(下)
文章图片

only会产生对象结果集,数据对象点only内出现的字段不会再操作数据库查询,不再only里的会再次操作数据库获得数据
res = models.Book.objects.only('bname', 'price') for i in res: print(i.bid) print(i.bname)

django框架|django框架——模型层(下)
文章图片

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')

    推荐阅读