• ORM之聚合查询,分组查询,F查询,Q查询,ORM查询优化,事务操作,常见字段及参数,多对多三种表的创建


    一:正反向进阶操作

    1.查询主键为1的书籍对应的出版社名称和书名

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

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

    models.Author.objects.filter(book__pk=3).values('name','book__title')
    
    • 1

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

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

    4.查询南方出版社出版的书籍的名称及价格

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

    5.查询jason写过的书名和日期

    models.Book.objects.filter(authors__name='jason').values('title', 'publish_date')
    
    • 1

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

    models.Author.objects.filter(book__pk=1).values('author_detail__phone')
    
    • 1
    models.AuthorDetail.objects.filter(author__book__pk=1).values('phone')
    
    • 1

    二:聚合查询

    1.首先第一步需要导入模块

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

    2.没分组之前聚合查询需要使用关键字aggregate

    models.Book.objects.aggregate(Max('price'), Min('price'),Count('pk'))
    
    • 1

    三:分组查询

    1.如何取消分组之后默认只能够获取分组字段的特性?
    • 将sql_mode中的only_full_group_by配置移除即可
    # 第一步:在终端进入mysql,输入以下指令
    set global sql_mode = 'STRICT_TRANS_TABLES'
    # 第二步:退出mysql
    # 第三步:重新进入mysql即可
    
    • 1
    • 2
    • 3
    • 4
    2.分组查询练习
    1.按照整条数据分组
    models.Book.objects.annotate()
    
    • 1

    案例1:统计每一本书的作者个数

    models.Book.objects.annotate(author_num=Count(authors__pk)).values('author_num')
    
    • 1
    2.按照表中某个字段分组

    按照annotate前面values括号中的字段分组

    models.Book.objects.values('title').annatate()
    
    • 1

    案例2:统计每一个出版社的数的数量

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

    案例3:统计出每个出版社卖的最便宜的书的价格

    models.Publish.objects.annotate(min_price=Min(book__price)).values('name','min_price')
    
    • 1

    案例4:统计不止一个作者的书

    models.Book.objects.annotate(author_num=Count('authors__pk')).filter(author_num__gt=1).values('title', 'author_num')
    
    • 1

    案例5:查询各个作者出的书的总价格

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

    四:F查询

    1.F查询条件不是自定义的,而是来自于表中的字段

    首先需要导入F模块

    from django.db.models import F
    
    • 1

    案例1:查询库存数大于卖出数的书籍

    models.Book.objects.filter(stock_num__gt=F('sale_num'))
    
    • 1

    案例2:将所有的书籍价格上涨1000块

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

    案例3:将主键为1的书籍名称加上爆款后缀

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

    五:Q查询

    1.默认是and关系

    models.Book.objects.filter(pk=1, publish_id=3)
    
    • 1

    2.逗号分割还是and关系

    models.Book.objects.filter(Q(pk=1), Q(piblish_id=3))
    
    • 1

    3…管道符是or的关系

    models.Book.objects.filter(Q(pk=1) | Q(publish_id=3))
    
    • 1

    4.波浪号是not关系

    models.Book.objects.filter(~Q(pk=1) | Q(publish_id=3))
    
    • 1

    5.Q查询可以可以将查询条件的字段改为字符串形式

    q_obj = Q()
    q_obj.connector = 'or'  # q对象默认的多个条件是and关系
    q_obj.children.append(('pk',1))
    q_obj.children.append(('publish_id',3))
    res = models.Book.objects.filter(q_obj)
    print(res)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    六:ORM查询优化

    1.django中orm自带的两个优化机制
    • 1.orm默认都是惰性查询:当后续需要的时候才会真正执行
    • 2.orm自带limit分页:减轻数据库和服务器端的压力
    2.only与defer
    2.1.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

    only会将括号内填写的字段封装成一个个的数据对象,对象在点击的时候不会再走数据库查询,但是对象点括号中没有的字段的时候,每次都会走数据库

    总结:对象点only括号内有的字段不会走数据库,点括号中没有的字段会走数据库

    2.2.defer
    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

    总结:对象点defer括号内有的字段会走数据库,点括号中没有的字段不会走数据库

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

    总结:

    • 1.select_related括号内只能接收外键字段(一对一,一对多)
    • 2.自动连表
    • 3.得到数据对象直接点表中的字段得到相应的数据
    • 4.不会再走数据库查询
    3.2prefetch_related
    res = models.Book.objects.prefetch_related('publish')
    for obj in res:
    	print(obj.publish.name)
    
    • 1
    • 2
    • 3

    总结:

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

    七:事务操作

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

    八:模型层常见的字段

    字段功能
    AutoField()int类型且自增,必须填入参数 primary_key=True
    CharField()主要存储字符串的数据类型
    IntegerField()存储整型数据
    BigIntegerField()大整型,只要用于存储整型的数据
    DateField()主要存储日期类型的数据类型,年月日
    DateTimeField()主要存储日期类型的数据类型,时分秒
    DecimalField()表示固定精度的十进制数的字段。它有两个必须的参数:max_digits:数字允许的最大位数decimal_places:小数的最大位数
    EmailField()邮件格式的数据
    BooleanField()传布尔值存数字0或1
    TextField()存储大段文本
    FileField()存储文件数据 自动找指定位置存储 字段存具体路径
    ForeignKey()外键字段
    OneToOneField()一对一外键字段
    ManyToManyField()多对多外键字段
    ORM自定义字段
    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
    info = MyCharField(max_length=32)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    九:ORM常见字段参数

    字段参数说明
    max_lengthCharField必须要设置该参数,不然会报错
    verboses_name相当于注释
    auto_now修改一次就重新记录一次此次修改的事件
    auto_now_add只有创建的时候记录,以后不会改变
    null用于表示某个字段可以为空。设置方式:null = True
    default为该字段的默认值,设置方式:default = ‘默认值’
    max_digits数字允许的最大位数
    decimal_places小数的最大位数
    unique=True用于表示该字段值在此表中必须是唯一的,建立唯一索引,设置方式:unique = True
    db_index=True将该字段设置为索引,设置方式:db_index = True
    to绑定外键字段对应的表
    to_field指定想要绑定的外键字段
    related_name给外键字段起别名
    choices

    当字段数据的可能性可以完全列举出来的时候 应该考虑使用该参数

    class UserInfo(models.Model):
            username = models.CharField(max_length=32)
            gender_choice = (
                (1, '男性'),
                (2, '女性'),
                (3, '其他'),
            )
            gender = models.IntegerField(choices=gender_choice)
    	userinfo_obj.get_gender_display()
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    on_delete
    参数功能
    models.CASCADE级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除
    models.SET_NULL当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空
    models.PROTECT当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除
    models.SET_DEFAULT当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值
    models.SET()当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数
    models.DO_NOTHING什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似

    十:多对多三种表的创建方式

    方式一:自动创建
    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
    • 优点:第三张表扩展性强
    • 缺点:无法使用正反向查询以及多对多四个方法
    方式三:半自动创建
    class Book(models.Model):
            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
    • 优点:扩展性强并且支持正反向查询
    • 缺点:无法使用多对多四个方法
  • 相关阅读:
    springboot 简单配置mongodb多数据源
    轻拍牛头(求约数C++)
    IEDA-Maven项目开发步骤
    HTML5+CSS3+移动web 前端开发入门笔记(一)
    【Python数据结构与算法】——(线性结构)精选好题分享,不挂科必看系列
    【刷题记录⑩】Java工程师丨字节面试真题(四)
    你好,Cartesi Rollups Alpha 0.7.0
    C++ 字符串
    [牛客网刷题 Day6] JZ27 二叉树的镜像
    国产智多晶FPGA基于Verilog的设计开发流程
  • 原文地址:https://blog.csdn.net/Yydsaoligei/article/details/126729542