• Django_分组聚合查询


    多表查询
    1. 增删改
    	一对多:先一后多,外键可以为对象或依赖表的主键(publish and book)
    	publish = Publish.objects.create()
    	Book.objects.create(....publish=publish|publish_id=publish.id)
    	删: 默认存在级联删除
    	改: book修改外键,外键一定存在
    	多对多:
    	关系表的获取(book(主键) and author)  book.author
    	增:book.author.add(作者对象们|主键们)
    	删: clear()清除    remove() 可删除单个作者
    	改: set([作者对象们|主键们])
    	
    2. 查
    	基于对象,正向找属性,反向找类名小写,多条记录类名小写_set
    	book.publish.first().name  (book 一定是对象,不是queryset)
    	publish.book_set.first().name
    	
    	
    	基于双下划线:
    	Book.objects.filter(id=1).values('publish__name')[0]  (values 查出的也是queryset)
    	publish.values('book__name')
    	
    

    今日内容

    1. 分组查询: 聚合结果   group_by()
    2. 聚合函数
    3. 字段
    

    分组查询(单独聚合查询 and 分组聚合查询---基于mysql)

    Book: id name price publish_date  publish
    
    聚合函数可以单独使用 ---- 整张表是一个大组
    select max(price) from book 
    聚合函数在分组下使用
    select max(price) as high_price from book group by publish having high_price > 50; 
    

    聚合查询---基于ORM

    聚合函数的使用场景:
    	单独使用:不分组,只查聚合结果
    	分组使用: 按字段分组,可查分组字段与聚合结果
    	
    导入聚合函数:
    from django.db.models import Avg,Max,Min,Count,Sum
    

    单独聚合查询:aggregate (聚集,合集)---不分组

    # 语法
    # 聚合函数: Max, Min,Sum, Avg, Count
    aggregate(别名=聚合函数(’字段‘)
    
    规则: 
    1. 可以同时对多个字段进行聚合处理: aggregate(name1= , name2= ...)
    2. 是QuerySet 对象的方法(all,filter)
    3. 返回值为dict类型
    4. 在aggregate之前的values操作没作用,被忽略
    
    例: 所有书中最贵的书的价格 
    dic = Book.objects.all().aggregate(high_price=max('price),low_price=min('price'))
    
    

    分组聚合查询: annotate (注释,做注解) --- 分组

    # 语法
    values('分组字段').annotate(别名=聚合函数(‘字段’).filter(聚合别名条件).values('取分组字段','取聚合字段别名'))
    
    规则:
    1. values --- annotate 分组组合, values控制分组的字段,annotate控制聚合字段
    2. values 可以按多个字段分组values('字段1‘,’字段2‘)
    3. 可以同时对多个字段进行聚合处理 annotate(别名1=max('price'),别名2=min('price'))
    4. 分组后的filter 代表having判断,只对聚合字段进行条件判断,(参数为非聚合或分组进行条件判断代表where判断)
    5. 取字段值 values() 省略默认取所有分组字段和聚合字段,也可以自己定义(对非分组或非聚合字段,该字段自动被变成分组字段)
    
    # 案例:每个出版社出版的最贵的书的价格高于50元的出版社名与最高价格
    # 思路:按出版社分组(从book出发),high_price=max('price'), filter(high_price__gt=50)
    # 每个组的价格最贵的
    Book.objects.all().values('publish__name').annotate(high_price=max('price').filter(high_price__gl=50).values('publish__name','high_price'))
    

    字段属性

    1. null: 默认Fasle(默认字段不能为空) , True 表示字段可为null
    2. blank: 默认False, True 表示字段可以为空
    3.choice: 限制了该选项字段值必须是指定的choice 中的一个 (元组套元组)
    	sex = models.SmallIntegerField(choice=((1,'man'),(2,'female')))
    	obj.get_sex_display()
    	有choices 这个字段的: 要取得’女‘或’男‘, get_字段名sex_display() --超出失效
    4. db_column: 自定义字段名	
       db_column='gender' 起别名该sex
    5. db_index : True 设置索引
    6. default: 字段默认值
    7. editable: 默认为True,  False: 不在 admin 界面显示
    8. primary_key : TRUE 为主键,
    9. unique: true 字段值不可重复
    
    

    字段

    1. AutoField(): 默认自增主键(primary_key=True)
    2. BooleanField(): 布尔字段, 对应database tinyint 类型
    3. CharField(): 字符类型(默认不为空)
    	max_length=20,null=True  可以为空
    4. DateField(): 年月日
    	auto_now = True  数据别更新就会更新时间
    	auto_now_add = True  数据第一次产生时
    5. DateTimeField(): 年月日时分秒
    	auto_now = True  数据别更新就会更新时间
    	auto_now_add = True  数据第一次产生时
    6. DecimalField(): 混合精度的小数类型
    	max_digits = 5,  含小数为的最大位数
    	decimal_places = 2 , 小数位数
    7. IntegerField(): 整型
    

    不常用字段

    
    

    关系字段

    1. ForeignKey(): 外键字段
    	to= 关联模型类  (一对多)
    	to_file = 关联字段,省略默认关联主键
    	on_delete (外键关联数据被删除时的操作)
    		models.CASCADE 级联删除
    		modles.PROTECT 抛出异常
    		models.SET_NULL 设置空值
    		modles.SET_DEFAULT 设置默认值
    		models.SET(value) 自定义值
    	related_name 自定义反向查询的字段名
    	db_constraint=False, 取消关联,但还可以使用链表查询
    总结: models.ForeignKey(to='related class name', null=True,on_delete=models.SET_NULL,db_constraint=False,related_name='本类名小写’)
    2. OneToOneField(): 一对一字段
    	同外键
    3, ManyToManyField() :多对多关系
    	to = 关联模型类
    	through=关联关系类
    	through_fields关联关系表中(本身字段,关联字段)
    

    断开外键关联的ForeignKey使用(一对多,一对一)

    # 一对多查询 ----(publish and book)
    # 方式一 : 不使用外键,在book 中添加 publish_id 属性
    # 不在支持Django ORM 链表查询语法
    
    # class Book(models.Model):
    #     name = models.CharField(max_length=20)
    #     publish_id = models.IntegerField(null=True)
    #
    # class Publish(models.Model):
    #     name = models.CharField(max_length=20)
    #
    # # 查询方式:
    # # 通过第一本书book  找出版社
    # # id = Book.objects.first().publish_id
    # # publish = Publish.objects.filter(id=id)[0].name
    # # print(publish)
    
    方式二:使用外键, 用db_constrain=False 字段段开连接
    # 可以使用Django ORM连表查询语法
    class Book(models.Model):
        name = models.CharField(max_length=20)
        publish = models.ForeignKey(to='Publish',db_constraint=False,null=True,on_delete=models.SET_NULL)   # to_field='id' 不写会自动添加
    
    class Publish(models.Model):
        name = models.CharField(max_length=20)
    
    # 书的出版社 (外键方式)
    # print(Book.objects.first().publish.name)
    # print(Book.objects.filter(pk=1).values('publish__name'))
    
    

    断开关联--- 多对多自动创建关系表

    # 断开关联(db_constraint属性)的多对多自动创建关系表  (book(外键) and author)
    # 断开后依然支持Django ORMlianiao 查询语法
    # 当新表中无需新加额外字段时, 可以自动创建
    class MyBook(models.Model):
        name = models.CharField(max_length=20)
        # 这里会产生第三张表
        book_author = models.ManyToManyField(to='MyAuthor',db_constraint=False)
    
    class MyAuthor(models.Model):
        name = models.CharField(max_length=20)
    
    
    # # 查询方法
    # # 多对多(自动创建第三张表): 书的作者
    # b1 = MyBook.objects.first()
    # # b1.book_author  这个是关系表
    # for author in b1.book_author.all():
    #     print(author.name)
    
    # print(MyBook.objects.filter(pk=1).values('book_author__name'))
    

    断开关联 --- 多对多手动创建关系表

    # 手动创建关系表的原因: 可以拥有自身字段,可以通过关系表类名直接获取第三张表
    
    
    # 手动创建关系表可以让关系表可以拥有更多的自身的字段,同时通过关系表类名可以直接获取第三张表
    '''
    # ****
    # 1、和自动建立关系表类似,依然支持Django ORM连表查询语法(多对多借助关系表连表查询)
    class Book(models.Model):
        name = models.CharField(max_length=20)
        
    class Author(models.Model):
        name = models.CharField(max_length=20)
        
    class Book_Author(models.Model):
        book = models.ForeignKey(to="Book", null=True, on_delete=models.SET_NULL, db_constraint=False)
        author = models.ForeignKey(to='Author', null=True, on_delete=models.SET_NULL, db_constraint=False)
        time = models.DateField()
    '''
    
    '''
    # ****
    2、手动创建关系表,在关系表中用ForeignKey方式支持基于外键关系表的ORM连表查询,同时明确ManyToManyField字段,所以也支持ORM正向方向连表查询
    	-- db_constraint=False断开关联可以在ForeignKey或ManyToManyField任意一方完成
    class Book(models.Model):
        name = models.CharField(max_length=20)
        # 明确through与through_fields,ManyToManyField才不会自动建立关系表,没有关联关系后就不能再使用db_constraint字段属性
        author = models.ManyToManyField(to='Author', through='Book_Author', through_fields=('book_id', 'author_id'))
        
    class Author(models.Model):
        name = models.CharField(max_length=20)
        
    class Book_Author(models.Model):
        book = models.ForeignKey(to="Book", null=True, on_delete=models.SET_NULL, db_constraint=False)
        author = models.ForeignKey(to='Author', null=True, on_delete=models.SET_NULL, db_constraint=False)
        time = models.DateField()
    '''
    # 总结:手动创建第三张表,第三张表的增删改就采用关系表类名衍生的create|delete|update,就不再拥有add|clear|remove|set(因为关系表拥有自己的字段,这些方法无法直接操作这些字段)
    
    
    
    
  • 相关阅读:
    sleep() 和 wait() 区别是什么?
    JAVA面试中需要准备的点
    javascript 取掉空格自定义函数
    code manager tools myeclipse10 svn插件安装及使用
    javascript 常用兼容fire fox的解决办法
    javascript 获取标签内的内容
    javascript dom与字符串相互转换
    javascript window.showModalDialog不兼容goole解决方案
    javascript js获取url及url参数解析
    javascript table排序之jquery.tablesorter.js
  • 原文地址:https://www.cnblogs.com/Afrafre/p/12799202.html
Copyright © 2020-2023  润新知