zoukankan      html  css  js  c++  java
  • Django之集合函数使用与mysql表的创建特殊字段分析

    1. 集合函数的使用场景:

      -- 单独使用: 不分组, 只查聚合结果

      -- 分组使用: 按字段分组, 可查询分组字段与聚合结果

    2. 导入聚合函数

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

    3. 单独聚合查询: aggregate

    # 语法:
    aggregate(别名=聚合函数('字段'))
    
    # 规则:
    1.可以同时对多个字段进行聚合处理:aggregate(别名1=聚合函数1('字段1'), ..., 别名n=聚合函数n('字段n'))
    3.是QuerySet对象方法
    2.方法返回值返回值为dict类型
    
    # 案例:所有书中最贵的书的价格
    Book.objects.all().aggregate(high_price=Max('price'))
    # 不分组单独使用的聚合函数 aggregate  把整个大表看成一个组
    #high_price 这个是自定义的别名 方便后期调用

    4. 分组聚合查询: annotate

    # 语法:
    values('分组字段').annotate(别名=聚合函数('字段')).filter(聚合字段别名条件).values('取分组字段', '取聚合字段别名')
    
    # 规则:
    1.values(...).annotate(...)为分组组合,values控制分组字段,annotate控制聚合字段
    2.values可按多个字段分组values('分组字段1', ..., '分组字段n'),??如果省略代表按操作表的主键分组
    3.可以同时对多个字段进行聚合处理annotate(别名1=聚合函数1('字段1'), ..., 别名n=聚合函数n('字段n'))
    4.分组后的的filter代表having判断,只对聚合字段进行条件判断,可以省略(对非聚合字段或分组字段进行条件判断代表where判断)
    5.取字段值values(...)省略默认取所有分组字段与聚合字段,也可以自主取个别分组字段及聚合字段(取字段的values中出现了非分组或非聚合字段,该字段自动成为分组字段)
    
    # 案例:每个出版社出版的最贵的书的价格高于50元的出版社名与最高价格
    Book.objects.all().values('publish__name').annotate(high_price=Max('price')).filter(high_price__gt=50).values('publish__name', 'high_price')
    # 案例:每个出版社出版的最贵的书的价格高于50元的出版社名与最高价格
    res = Book.objects.values('publish__name')
        .annotate(high_price=Max('price'))
        .filter(high_price__gt=50)
        .values('publish__name', 'high_price')
    print(res)
    
    #注意 'publish__name' 这个就是分组的字段
    # 注意 high_price=Max('price')  就是自定义别名
    # 注意 filter(high_price__gt=50) 就是分组后的过滤条件, 等于mysql中的having 函数
    # 注意 values('publish__name', 'high_price')  最后取值 一定取分组字段与自定义别名
    
    
    res = Publish.objects.values('name')
        .annotate(high_price=Max('book__price'))
        .filter(high_price__gt=50)
        .values('name', 'high_price')
    print(res)

    mysql表的创建常用字段属性解析

    '''
    1. null:默认为False,True表示字段可为null
    2. blank:默认为False,True表示字段可为空
    3. choice:可选的,限制了该选项的字段值必须是所指定的choice中的一个:
        -- sex = models.SmallIntegerField(choices=((1, '男'), (2, "女")))
        -- obj.get_sex_display()
    4. db_column:自定义字段名
    5. db_index:如果为True的话,设置索引
    6. default:字段默认值
    7. editable:默认为True,若为False,则不会在/admin/界面显示
    8. primary_key:若设置为True,则表示将该字段设置为主键。一般情况下django默认会设置一个自增长的id主键。
    9. unique:若设置为True,该字段值不可重复
    '''
    设置表的字段类型:
    '''
    1. AutoField():默认自增主键(primary_key=True),django会默认建立id字段主键
    2. BooleanField():布尔字段,对应数据库tinyint类型
    3. CharField():字符类型
        -- 字段属性max_length=64,数据长度,必须明确
    4. DateField():年月日时间类型
        -- 字段属性auto_now=True,数据被更新就会更新时间
        -- 字段属性auto_now_add=True,数据第一次参数时产生
    5. DateTimeField():年月日小时分钟秒时间类型
        -- 字段属性auto_now=True,数据被更新就会更新时间
        -- 字段属性auto_now_add=True,数据第一次参数时产生
    6. DecimalField():混合精度的小数类型
        -- 字段属性max_digits=3,限定数字的最大位数(包含小数位)
        -- 字段属性decimal_places=2,限制小数的最大位数
    7. IntegerField():整型
    '''
    '''
    1. ForeignKey():外键字段
        -- 字段属性to关联模型类
        -- 字段属性to_field关联字段,省略默认关联主键
        -- 字段属性on_delete (外键关联数据被删除时的操作)
            -- models.CASCADE 级联删除
            -- modles.PROTECT 抛出异常
            -- models.SET_NULL 设置空值
            -- models.SET_DEFAULT 设置默认值
            -- models.SET(value)自定义值
        -- 字段属性related_name自定义反向查询的字段名
        -- 字段属性db_constraint=False取消关联关系,但还可以使用连表查询
    总结:models.ForeignKey(to='关联的类名', null=True, on_delete=models.SET_NULL, db_constraint=False, related_name="本类名小写")
    
    2、OneToOneField():一对一外键字段
        -- 字段同外键
    3、ManyToManyField():多对多关系字段
        -- 字段属性to关联模型类
        -- 字段属性through关联关系类
        -- 字段属性through_fields关联关系表中(本身类名小写字段, 关联表类名小写字段)
    '''
    关系字段-表与表关联的字段设置详解
    # 2、使用ForeignKey方式用db_constraint=False字段属性断开关联,依然支持Django ORM连表查询语法,建议使用
    class Publish(models.Model):
        name = models.CharField(max_length=20)
    class Book(models.Model):
        name = models.CharField(max_length=20)
        # 字段不需要写_id来表示相关表的字段信息,ORM会自动添加
        publish = models.ForeignKey(to='Publish', null=True, on_delete=models.SET_NULL, db_constraint=False)
        
    '''
    一对多关系Foreignkey用法
    # *****
    # 使用ManyToManyField方式用db_constraint=False字段属性断开关联,依然支持Django ORM连表查询语法,建议使用
    class MyBook(models.Model):
        name = models.CharField(max_length=20)
        my_author = models.ManyToManyField(to='MyAuthor', db_constraint=False)
    class MyAuthor(models.Model):
        name = models.CharField(max_length=20)
    '''
    断开关联关系的多对多自动建表

    建表的案例:

    from django.db import models
    
    # Create your models here.
    
    # Book书籍:id  name  price  publish_date  publish(publish_id)
    class Book(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=20)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        publish_date = models.DateField()
        # 在2.x环境下外键要明确on_delete字段属性
        publish = models.ForeignKey(to='Publish', to_field='id', on_delete=models.CASCADE)
        author = models.ManyToManyField(to='Author')
    
    # 给你Book与Author
    
    # Author作者:id  name
    class Author(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=20)
        author_detail = models.OneToOneField(to='AuthorDetail', to_field='id', on_delete=models.CASCADE)
    
    
    # AuthorDetail作者详情: id  age  telephone  info
    class AuthorDetail(models.Model):
        id = models.AutoField(primary_key=True)
        age = models.IntegerField()
        telephone = models.BigIntegerField()
        info = models.TextField()
    
    
    # Publish出版社:id  name  address
    class Publish(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=20)
        address = models.CharField(max_length=64)
    
    
    
    class UserInfo(models.Model):
        id = models.AutoField(primary_key=True)
        name = models.CharField(max_length=20)
        age = models.IntegerField()
        gender = models.SmallIntegerField()
        province = models.CharField(max_length=20)
        city = models.CharField(max_length=20)
    
    
    class Test1(models.Model):
        a1 = models.CharField(max_length=20)  # 插入数据时该字段必须赋值
        a2 = models.CharField(max_length=20, null=True)  # 插入数据时可以为空
    
        # choices为元组套元组,子元组的第一个值类型要与字段类型对应,
        # 第二个值可以代表第一个值得特殊含义
        # 通过get_tagName_display()获取特殊含义
        choices = ((0, ''), (1, ''))
        sex = models.SmallIntegerField(choices=choices, default=0, db_column='gender')
    
        res = models.BooleanField(default=False)
    
    
    
    class Test2(models.Model):
        name = models.CharField(max_length=20)
        test1 = models.ForeignKey(to='Test1', null=True, on_delete=models.SET_NULL, db_constraint=False, related_name="tt")
    建表的案例模板分析

     基于orm的优化查询方案:

    # only: 只取规定的字段形成对象(查主键)
    # uq11 = Uesr.objects.all().only('name', 'age')
    # print(uq11)
    # print(uq11.query)
    # print(uq11.first().name)
    # print(uq11.first().gender)  # 自己又重新执行了查询该字段的sql
    #
    # defer:只取规定的字段外的字段形成对象(查主键)
    # uq12 = Uesr.objects.all().defer('name', 'age')
    # print(uq12)
    # print(uq12.query)
    #
    # 好处:只对所需字段进行查询
    # 坏处:数据放在字典中,相比对象取值不是那么方便
    # uq2 = Uesr.objects.values('name', 'age')
    # print(uq2)
    # print(uq2.query)
    优化查询有only 与defer两种方案
  • 相关阅读:
    Leetcode 611.有效三角形的个数
    Leetcode 606.根据二叉树创建字符串
    Leetcode 605.种花问题
    潘潘_策略投资:期货存在跨期套利和跨品种套利的机会
    雷公资本:我的交易系统02 --- 可预知的趋势
    西子凌波47:回答问题 2016-10-28
    西子凌波43:说几句 2016-03-07
    西子凌波39:当下状态2 (2015-11-07 22:33:22)
    西子凌波36:放假了。说一些题外话。 2015-09-04
    西子凌波35:简单的走势,还有不明白的吗? 2015-08-21
  • 原文地址:https://www.cnblogs.com/gukai/p/10773278.html
Copyright © 2011-2022 走看看