zoukankan      html  css  js  c++  java
  • Django之模型层02

    一、聚合查询与aggregate方法

      1、聚合查询通常都是配合分组查询一起使用的,若需单独使用,要通过aggregate方法。

      2、需要导入的模块:

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

      3、实例:

        task_obj_set = models.Task.objects.all()
        print(task_obj_set.aggregate(Max('time_limit')))  # 最大值
        print(task_obj_set.aggregate(Min('time_limit')))  # 最小值
        print(task_obj_set.aggregate(Sum('time_limit')))  # 值之和
        print(task_obj_set.aggregate(Count('time_limit')))  # 值个数
        print(task_obj_set.aggregate(Avg('time_limit')))  # 值的均数
        # 也可以把多个聚合函数写在一个aggregate()里面

    二、分组查询---annotate方法

      1、实例:

        # 一、统计每个task的hunter的个数
        task_obj_set = models.Task.objects.all()  # 不作其他声明,默认每个记录是一组
        # 需要给聚合查询的结果绑定一个名字,后续可以以该名字查询
        print(task_obj_set.annotate(hunter_num=Count('hunter__pk')).values('area', 'hunter_num'))
        # __pk 也可以省略不写,效果一样
        print(task_obj_set.annotate(hunter_num=Count('hunter')).values('time_limit', 'hunter_num'))
        # 二、统计每个level的hunter的more_info的real_age最大值
        level_obj_set = models.Level.objects.all()
        print(level_obj_set.annotate(max_real_age=Max('hunter__more_info__real_age')).values('name', 'max_real_age'))
        # 三、统计每个hunter的task的time_limit的平均数大于等于72的具体值
        hunter_obj_set = models.Hunter.objects.all()
        print(hunter_obj_set.annotate(avg_time=Avg('task__time_limit')).filter(avg_time__gt=72).values('code_name', 'avg_time'))

      2、按照指定字段分组:

        # hunter_moro_info的real_age相同的为一组,统计每组的hunter的task的的time_limit之和
        hunter_more_info_obj_set_by_real_age = models.HunterMoreInfo.objects.values('real_age')
        print(hunter_more_info_obj_set_by_real_age.annotate(sum_time=Sum('hunter__task__time_limit')).values('real_name', 'sum_time'))

    三、F查询

      1、通过F查询可以直接获取某个字段对应的记录。

      2、需要导入的模块:

        from django.db.models import F

      3、实例:

        # 一、查找hunter的look_age比out_age大的more_info的real_name和real_age
        hunter_obj_set = models.Hunter.objects.all()
        print(hunter_obj_set.filter(look_age__gt=F('out_age')).values('more_info__real_name', 'more_info__real_age'))
        # 二、将所有task的time_limit增加24
        task_obj_set = models.Task.objects.all()
        task_obj_set.update(time_limit=F('time_limit') + 24)

      4、F查询配合Concat与Value功能实现字符串拼接:

        ①需要导入的模块:

        from django.db.models.functions import Concat
        from django.db.models import Value

        ②实例:

        level_obj_set = models.Level.objects.all()
        level_obj_set.update(right=Concat(Value('权限:'), F('right')))

    四、Q查询

      1、打破只能用逗号进行与运算的限制,可以通过Q查询可以进行更多的关系运算。

      2、需要导入的模块:

        from django.db.models import Q

      3、实例:

        hunter_obj_set = models.Hunter.objects.all()
        # 一、查询hunter的out_age大于等于18,且小于等于20的code_name和out_age
        # 逗号---and
        print(hunter_obj_set.filter(Q(out_age__gte=18), Q(out_age__lte=20)).values('code_name', 'out_age'))
        # 二、查询hunter的out_age小于18,或大于20的code_name和out_age
        # 竖杠---or
        print(hunter_obj_set.filter(Q(out_age__lt=18) | Q(out_age__gt=20)).values('code_name', 'out_age'))
        # 三、查询hunter的out_age不在20到100之间的code_name和out_age
        # 波浪号---not
        print(hunter_obj_set.filter(~Q(out_age__range=[20, 100])).values('code_name', 'out_age'))

      4、Q查询对象化的用法:

        # 查询hunter的'out_age'小于20,或'look_age'大于50的code_name,查询条件必须是字符串
        hunter_obj_set = models.Hunter.objects.all()
        # 方式一
        # 先生成两个Q查询对象
        q_obj_1 = Q()
        q_obj_2 = Q()
        q_obj_1.children.append(('out_age__lt', 20))
        q_obj_2.children.append(('look_age__gt', 50))
        # 再把对象作为条件查询
        print(hunter_obj_set.filter(q_obj_1 | q_obj_2).values('code_name'))
        # 方式二
        # 用同一个Q查询对象,修改内部默认子条件关系运算的符号
        q_obj_3 = Q()
        q_obj_3.connector = 'or'  # 默认 'and'
        q_obj_3.children.append(('out_age__lt', 20))
        q_obj_3.children.append(('look_age__gt', 50))
        print(hunter_obj_set.filter(q_obj_3).values('code_name'))

    五、开启事务

      1、需要导入的模块:

        from django.db import transaction

      2、基本语句结构:

        try:
            # with 代码块内的orm语句同属于一个事务
            with transaction.atomic():
                # orm语句1
                # orm语句2
                pass
        except Exception as e:
            print(e)

    六、常用字段及参数汇总

      1、通用参数:

        ①verbose_name:字段的描述。

        ②db_index:将该字段设置为索引。

      2、AutoField:一般用于主键字段,且一般 也不手动创建,orm会自动以'id'为名,创建主键字段。

        ①primary_key = True,设置为主键 。

      3、CharField:不定长字符串。

        ①max_length:最大长度。

      4、IntegerField:整型。

      5、BigIntegerField:长整型。

      6、DecimalField:浮点型。

        ①max_digits:最大总长。

        ②decimal_places:小数部分固定长度。

      7、EmailField:邮箱格式字符串。

      8、DateField:日期格式,年月日。

      9、DateTimeField:日期格式,年月日时分秒。

        ①auto_now=True,动态值,每次修改记录会自动更新为当时的时间。

        ②auto_now_add=True,固定值,记录创建数据时时候,后续不会再更改。

      10、BooleanField:布尔型,True/False 对应到数据库会转化为 1/0。

      11、TextField:长字符串,可以接收大段长文本,没有长度限制。

      12、FileField:文件类型。

        ①upload_to='xxxooo tt',给该字段传一个文件对象,会将文件数据保存于该目录下,另外将文件路径保存到数据库中。

      13、更多字段详情,参考鸡哥博客:https://www.cnblogs.com/Dominic-Ji/p/9203990.html。

      14、自定义字段,在models.py中:

    class MyField(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({})'.format(self.max_length)
    
    
    class Xoo(models.Model):
        name = MyField(max_length=100, null=True, verbose_name='测试')

      16、OneToOneField:一对一字段。

      17、ManyToManyField:多对多字段。

      18、ForeignKey:外键字段,默认一对多。

        ①unique=True:设置成一对一,效果等同于OneToOneField。

        ②to_field:设置关联表的关联字段,一般不设置,就是默认关联主键。

        ③on_update/on_delete:设置当关联表更新/删除关联的记录记录时,本表对应的行为,在django2.0+/3.0+中需要通过此参数设置为级联更新/删除,而1.0+是默认级联更新/删除的。

    七、数据库查询优化

      1、only与defer:

        ①models.Book.objects.all():一次性从数据库获得完整的记录对象集,可以通过记录对象查看任意字段,不需要再访问数据库。

        ②models.Book.objects.only('xxx'):从数据库获得的记录对象集,只携带了'xxx'字段的记录,只有查看'xxx'字段不需要再访问数据库,查其他字段还需要重新访问数据库。

        ③models.Book.objects.defer('xxx'):从数据库获得的记录对象集,携带了除'xxx'字段的以外的其他所有记录,只有查看'xxx'字段才需要重新访问数据库,查其他字段则不需要再访问数据库。

        ④小结:使用哪种方法能够更节约io时间,需要看表的字段个数以及每个字段的记录多少等综合考虑。

      2、select_related与prefetch_related:

        ①models.Hunter.objects.all().select_related('level'):先连表,类似于获得大表对象,后续对大表对象中的所有字段的查询都不需要再访问数据库。

        ②models.Hunter.objects.all().prefetch_related('task'):子查询,比连表会多访问一次数据库。

        ③小结:使用哪种方法能够更节约io时间,需要综合比较连表的时间和额外访问数据库的时间。

      

  • 相关阅读:
    基于IDEA+Maven+SpringMVC的入门web程序分析(一)
    Spring之路----chapter03 高级装配
    Spring之路---chapter02装配Bean
    Spring之路----Chapter01 Spring之旅
    实用网址-项目的创建、Idea打开Maven项目、Idea打开Eclipse项目
    Git之路-2017年9月8日14:37:01
    Redis入门指南-笔记-进阶
    DenyHosts 阻止SSH暴力攻击
    某cms最新版前台RCE漏洞(无需任何权限)2020-03-15
    通过Joomla的两次RCE漏洞看session反序列化
  • 原文地址:https://www.cnblogs.com/caoyu080202201/p/13027384.html
Copyright © 2011-2022 走看看