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) '''
# ***** # 使用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")