django框架——模型层(下)

系列文章目录

第一章 django安装与介绍

第二章 django基础使用

第三章 路由层

第四章 虚拟环境、django版本区别、视图层

第五章 模板层

第六章 模型层(上)

第七章 模型层(下)



一、聚合查询

相当于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 Value

res = 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')
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值