• Day60 django ORM 分组查询 查询优化 字段参数


    Day60 django ORM 分组查询 查询优化 字段参数

    1、正反向查询进阶

    查询主键为1的书籍对应的出版社

    res = models.Publish.objects.filter(book__pk=1).values('name','book__title')
    print(res)
    
    • 1
    • 2

    查询主键为3的书籍对应的作者姓名及书名

    查询主键为3的书籍对应的作者姓名及书名
    
    • 1

    查询jason的作者的电话号码和地址

    res = models.AuthorDetail.objects.filter(author__name='jason').values('phone','addr')
    print(res)
    
    • 1
    • 2

    查询南方出版社出版的书籍名称和价格

    res = models.Book.objects.filter(publish__name='南方出版社').values('title','price')
    print(res)
    
    • 1
    • 2

    查询jason写过的书的名称和日期

    res = models.Book.objects.filter(authors__name='jason').values('title','publish_time')
    print(res)
    
    • 1
    • 2

    查询电话是110的作者姓名和年龄

    res = models.Author.objects.filter(author_detail__phone=138).values('name','age')
    print(res)
    
    • 1
    • 2

    查询主键为1的书籍对应的作者电话号码

    res = models.Author.objects.filter(book__pk=1).values('author_detail__phone')
    print(res)
    
    • 1
    • 2

    2、聚合查询

    聚合函数:max、min、sum、avg、count

    聚合查询
    需要导入模块

    from django.db.models import Max,Min,Sum,Avg,Count
    
    • 1

    没有分组之前 单纯的使用聚合函数 需要关键字aggregate

    res = models.Book.objects.aggregate(Max('price'),Min('price'),Avg('price'),Sum('price'),Count('pk'))
    print(res)
    
    • 1
    • 2

    3、分组查询

    **分组有一个特性 默认只能够 直接获取分组的字段 其他字段需要使用方法 **
    我们也可以忽略掉该特性 将sql_mode中only_full_group_by配置移除即可

    1. 按照整条数据分组

      models.Book.objects.annotate()按照一条条书籍记录分组

    2. 按照表中某个字段分组

      models.Book.objects.values('title').annotate()按照annotate之前values括号中指定的字段分组

    统计每一本书的作者个数

    res =models.Book.objects.annotate(authors_number=Count('authors__pk')).values('title','authors_number')
    print(res)
    
    • 1
    • 2

    按照 字段分组

    res1 = models.Book.objects.values('publish_id').annotate(book_num=Count('pk')).values('publish_id','book_num')
    print(res1)
    
    • 1
    • 2

    统计出每个出版社卖的最便宜的书的价格

    res = models.Publish.objects.annotate(book_price=Min('book__price')).values('name','book_price')
    print(res)
    
    • 1
    • 2

    统计不止一个作者的图书

    res = models.Book.objects.annotate(authors_num=Count('authors__pk')).filter(authors_num__gt=1).values('title')
    print(res)
    
    • 1
    • 2

    查询各个作者出的书的总价格

    res = models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
    print(res)
    
    • 1
    • 2

    4、F查询与Q查询

    当表中已经有数据的情况下 添加字段需要指定一些参数

    1. 设置字段值允许为空 null=True
    2. 设置字段默认值 defqult=1000
    3. 在终端中直接给出默认值 provide

    4.1、F查询

    F查询:查询条件不是 自定义的 而是来自于表中其他字段

    from django.db.models import F,Q
    
    • 1

    查询库存数大于卖出数的书籍

    res = models.Book.objects.filter(storage_num__gt=F('sale_num'))
    print(res)
    
    • 1
    • 2

    将所有书籍的价格上涨 1000块

    models.Book.objects.update(price=F('price')+1000)
    
    • 1

    将所有书籍名称加上爆款后缀
    F查询 针对字符串 数据无法直接拼接

    from django.db.models.functions import Concat
    from django.db.models import Value
    models.Book.objects.filter().update(title = Concat(F('title'),value('爆款')))
    
    • 1
    • 2
    • 3

    4.2、Q查询

    Q查询:可以改变filter括号内多个条件之间的逻辑运算符 还可以将查询条件的字段 改为字符串形式
    导入模块

    from django.db.models import F,Q
    
    • 1
    res = models.Book.objects.filter(pk=1,publish_id=3)  #默认是and关系
    print(res)
    
    res = models.Book.objects.filter(Q(pk=1),Q(publish_id=3)) #Q查询 逗号连接 还是and关系
    print(res)
    
    res = models.Book.objects.filter(Q(pk=1)|Q(publish_id=3))  # Q查询 管道符连接 是ro关系
    print(res)
    
    res = models.Book.objects.filter(~Q(pk=1)|Q(publish_id=3))  #Q前加波浪 是取反 not
    print(res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    Q查询还可以将查询的字段改为字符串形式

    q_obj = Q()
    q_obj.connector='or'  #q对象默认是多个条件 也是and关系 可以修改为or
    q_obj.children.append(('pk',1))
    q_obj.children.append(('pin;ish_id',3))
    res = models.Book.objects.filter(q_obj)
    print(res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    5、ORM查询优化

    django orm默认都是惰性查询
    当orm的语句在后续的代码中真正需要使用的时候才会执行

    django orm自带limit分页
    减轻数据库端以及服务端的压力

    5.1、ORM查询优化之only

    用only 查询返回数据对象 封装了括号里写的字段 但这个对象 也支持括号里没有的字段名 但是它会去数据库里面查这个值

    res = models.Book.objects.only('title','price')
    for obj in res:
         print(obj.title)
         print(obj.price)
         print(obj.publish_time)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.2、ORM查询优化之defer

    defer 与only刚好相反 数据对象点击括号内出现的字段 每次都会走数据库查询 数据对象点括号内没有的字段 不会走数据库查询

    res = models.Book.objects.defer('title', 'price')
    for obj in res:
        # print(obj.title)
        # print(obj.price)
        print(obj.publish_time)
    
    • 1
    • 2
    • 3
    • 4
    • 5

    5.3、select_related

    res = models.Book.objects.all()
    for obj in res:
         print(obj.publish.name)  # 频繁走数据库查询
    
    • 1
    • 2
    • 3

    select_related 括号内只能接收外键字段(一对多 一对一)自动连表 得出的数据对象在点击表中数据的时候不会再走数据库查询

    res = models.Book.objects.select_related('publish')
    for obj in res:
    	print(obj.name)
    
    • 1
    • 2
    • 3

    5.4、prefetch_related

    prefetch_related底层其实是子查询 将查询之后的结果也一次性封装到数据对象中 用户在使用的时候是感觉不出来的

    res = models.Book.objects.prefetch_related('publish')
    for obj in res:
        print(obj.publish.name)
    
    • 1
    • 2
    • 3

    6、事物操作

    事物:ACID
    事物隔离级别:脏读、幻读、不可重复度
    原生sql:**start transaction\rollback\commit\savepoint **

    from django.db import transaction
        try:
            with transaction.atomic():
                pass  # 多条ORm语句
        except Exception as e:
            print(e)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    7、模型层常见字段

    AutoField() # int自增列
    CharField()  # 字符类型
    IntegorField() # 一个整数类型
    BigIntegerField()  #长数型(有符号)
    DateField()  # 日期字段
    DateTimeField()  #日期时间端
    DecimalField()   #十进制 小数
    EmailField()  # 字符串类型,提供验证机制
    BooleanField()  # 传布尔值存数字0或1
    TextField()  # 存储大段文本
    FileField()  # 存储文件数据  自动找指定位置存储 字段存具体路径
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    **关系字段 **

    class MyCharField(models.Field):
        def __init__(self, max_length, *args, **kwargs):
            self.max_length = max_length
            super().__init__(max_length=max_length, *args, **kwargs)
    
        def db_type(self, connection):
            return 'char(%s)' % self.max_length
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    自定义字段

    class MyCharField(models.Field):
        def __init__(self, max_length, *args, **kwargs):
            self.max_length = max_length
            super().__init__(max_length=max_length, *args, **kwargs)
    
        def db_type(self, connection):
            return 'char(%s)' % self.max_length
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    8.1、常见字段参数

    max_length  #最大 长度
    
    verboses_name  # 备注
    
    auto_now  # 配置上auto_now=True,每次更新数据记录的时候会更新该字段。
    auto_now_add  # 配置auto_now_add=True,创建数据记录的时候会把当前时间添加到数据库。
    
    null  #表示某个字段可以为空
    
    default  #为该字段设置默认值
    
    max_digits # 总位数
    
    unique=True #该字段在此表中必须是唯一的
    
    db_index=True  #代表着为此字段设置索引
    
    choices  #当字段数据的可能性是可以完全列举出来的时候 应该考虑使用该参数  性别、学历、成绩  
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    创建 选项 字段

    class UserInfo(models.Model):
            username = models.CharField(max_length=32)
            gender_choice = (
                (1, '男性'),
                (2, '女性'),
                (3, '其他'),
            )
            gender = models.IntegerField(choices=gender_choice)
    
    #获取 值       
    user_obj = models.UserInfo.objects.filter(pk=1).first()
    print(user_obj.gender)  #获取数据库中存的真实数据
    print(user_obj.get_gender_display()) #获取真实数据对应的数据
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    关联字段 参数

    to  # 设置要关联的表
    to_field  # 设置要关联的字段
    related_name  # 起别名
    on_delete  # 当删除关联表中的数据时,当前表与其关联的行的行为。(参考上面的例子)
    
    • 1
    • 2
    • 3
    • 4

    级联参数

    1、models.CASCADE
    级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
    2、models.SET_NULL
    当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
    3、models.PROTECT
    当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
    4、models.SET_DEFAULT
    当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
    5、models.SET()
    当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
    6、models.DO_NOTHING
    什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    9、多对多三种创建方式

    自动创建

    authors = models.ManyToManyfield(to='Author')
    
    • 1
    • 优点: 第三章表自动创建
    • 缺点: 第三张表 扩展性差

    手动创建

    class Book(models.Model):
        pass
    class Author(models.Model):
        pass
    class Book2Author(models.Model):
        book_id = models.Foreignkey(to="Book")
        author_id = models.Foreignkey(to="Author")
    优点:第三张表扩展性强
    缺点:无法使用正向反向查询以及多对多四个方法
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 优点: 第三张表扩展性强
    • 缺点: 无法使用正向反向查询以及多对多四个方法

    半自动创建

    class Book(models.Model):
        #to 关联的表  through=第三章表   #  through_fields(外键字段的表名,被关联的表)
        authors=models.ManyToManyField(to='Author',through='Book2Author',through_fields=('book_id','author_id') )
                                       
                                    
                                    
    class Author(models.Model):
            pass
    
    class Book2Author(models.Model):
        book_id = models.ForeignKey(to='Book')
        author_id = models.ForeignKey(to='Author')               
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 优点: 扩展性强并且支持正反向查询
    • 缺点: 无法使用多对多四个方法
  • 相关阅读:
    javaScript语法
    TCP/IP(九)TCP的连接管理(六)TIME_WAIT状态探究
    【小程序源码】uni-app云开发的网盘助手抓取网盘资源
    六.方法与接口
    [附源码]计算机毕业设计springboot超市商品管理
    Java进阶篇--并发容器之BlockingQueue
    Docker部署MySQL双主双从,主主互备
    二维码智慧门牌管理系统:提升社会治理水平,创新市民服务方式
    目标检测常见问题
    【669. 修剪二叉搜索树】
  • 原文地址:https://blog.csdn.net/weixin_71967396/article/details/126732930