models.py的模型结构
# -*- coding: UTF-8 -*-
from django.db import models
class Author(models.Model):
"作者模型"
name = models.CharField(max_length=100)
age = models.IntegerField()
email = models.EmailField()
class Meta: #该名称不能更改
db_table = 'author' #映射到数据库中为你自定义的名字,不设置这个默认为 包名_表名 映射到数据库
class Publisher(models.Model):
"出版社模型"
name = models.CharField(max_length=300)
class Meta:
db_table = 'publisher'
class Book(models.Model):
"book模型"
name = models.CharField(max_length=300)
pages = models.IntegerField()
price = models.FloatField()
rating = models.FloatField()
author = models.ForeignKey(Author,on_delete = models.CASCADE)
publisher = models.ForeignKey(Publisher,on_delete=models.CASCADE)
class Meta:
db_table = 'book'
class BookOrder(models.Model):
"图书订单模型"
book = models.ForeignKey("Book",on_delete=models.CASCADE)
price = models.FloatField()
class Meta:
db_table = 'book_order'
聚合函数
在views.py中
1.Avg : 求平均值
from django.shortcuts import render
from django.http import HttpResponse
from .models import Book
from django.db.models import Avg
from django.db import connection
def index(request):
#获取book表下的价格(price字段)求平均价(平均值)
result = Book.objects.aggregate(Avg('price')) #Avg不能直接使用,需要使用aggregate包住
print(result)
print(connection.queries) #可以查看被翻译成的sql语句,需要导入connection, 如果是queryset的话就可以使用query进行查询
return HttpResponse('index')
这时候django就会自动给你创建一个别名,也就是 字段名__Avg,如果想要更给改的话
#这时候django就会自动给你创建一个别名,也就是 字段名__Avg,如果想要更给改的话
result = Book.objects.aggregate(price_avg=Avg('price')) #Avg不能直接使用,需要使用aggregate包住
关于 aggregate 和 annotate 执行聚合函数的方法
例子 : 比如在求平均值
#1.aggregate 会将所有的值都会求出平均值(需要导入connection模块)
def index(request):
result = Book.objects(Avg('price')) #Avg不能直接使用,需要使用aggregate包住详情看1的写法
print(result) #2.annotate 的话就会一个额外的 group by的分组操作,然后在求出各个组的平均值 #求各组的平均值 #将Book表下关联的BookOrder(使用的话就django默认设置的小写)的price字段中根据id的不同分组,然后在求出各个组的平均值 books = Book.objects.annotata(price_avg=Avg('bookorder__price')) #将这个名称改了price_avg for book in books: print('%s/%s'%(book.name,book.price_avg)) #price_avg在前面中已经更改了名称,不然就是默认的Avg
Count 求每个表中有多少个id(也就是求总数)
from django.http import HttpResponse
from .models import Book,Author,BookOrder
from django.db.models import Avg,Count
from django.db import connection
#1. Count 求每个表中有多少个id(也就是求总个数)
# result = Book.objects.aggregate(book_nums =Count('id')) #book_nums自定义关键字参数,用户接收返回的数据
# print(result)
# print(connection.queries) #查看转换成的sql语句
#2.统计 Author 表下的有多少个不同的邮箱(也就是使用count统计相同的邮箱时只算一个,而不是全部统计)- 也就是distinct=True
# result = Author.objects.aggregate(email_nums =Count('email',distinct=True)) #email_nums自定义关键字参数,用户接收返回的数据
# print(result)
# print(connection.queries) #查看转换成的sql语句
# 3. 使用 annotate 来统计每个分组的具体个数( 换言之也就是求每个组的销量等等这样的就可以使用这个方法 )
books = Book.objects.annotate(book_nums=Count('bookorder__id')) #bookorder__id 也就是bookorder表下的id字段
for book in books:
print('%s/%s'%(book.name,book.book_nums)) #使用了book_nums自定义参数那么这个表就自动增加了这个属性
Max 和 Min 获取指定对象(某字段)的最大值和最小值
from django.db.models import Avg,Count,Max,Min
# 1. Max 和 Min 获取指定对象(某字段)的最大值和最小值
result = Author.objects.aggregate(max=Max('sge'),min=Min('age')) #求这个Author表下的年龄字段的最大值和最小值,max和min是自定义的,用来接收值
print(request)
print(connection.queries)
#同理也可以使用annogate分组求每本书的最大值和最小值
Sum : 求某个字段的总和
from .models import Book,Author,BookOrder
from django.db.models import Avg,Count,Max,Min,Sum
#如果有漏的在自行导入,这只是一个大概例子
#1. 求所有图书的销售总额,也就是所有卖出的书的总和
# result = BookOrder.objects.aggregate(total=Sum('price')) #求出BookOrder表下price字段的总和
# print(request)
# print(connection.queries)
#2. 单独求出每一本书的销售总额(也就是关于三国演义这本书以及红楼梦这本书都各卖了多少钱)-需要到分组也就是 annotate
books = BookOrder.objects.annotate(total=Sum('bookorder__id')) #对bookorder__id这个字段做一个分组,然后求出每个分组的总额,然后使用自定义的total接收
for book in books:
print('%s%s'%(book.name,book.total)) #这个total是上面自定义的,自定义好厚就会为这个表添加上这个属性
print(connection.queries)
#3.求某一年的销售总额 - 这里只提供思路
# ①先获取某一年的数据 表名.objects.filter 回顾之前的时间查询条件
# ②再根据这些数据使用Sum求出来即可 ,使用正常的 aggregate 和 Sum
#4.求每一种书在某一年的销售总额,也就是三国演义在2018年一共卖了多少钱,红楼梦在2015一共卖了多少钱
#①先获取某一年的数据 表名.objects.filter 回顾之前的时间查询条件
#②再根据这些数据使用Sum求出来即可 ,使用正常的 annotate 和 Sum