django2.0 ORM聚合函数的使用:aggregate与annotate


发布时间:2019-02-15 13:08    作者: Uncle Hui   已过去:1 年,3 月   阅读总量:956 已被赞:3


学习模型准备:

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):
    """图书模型"""
    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()
    create_time = models.DateTimeField(auto_now_add=True,null=True)

    class Meta:
        db_table = 'book_order'

1. 所有的聚合函数都是放在`django.db.models`下面。

例如:

from django.db.models import Avg,Count,Max,Min,Sum
2. 聚合函数不能够单独的执行,需要放在一些可以执行聚合函数的方法下面中去执行。比如`aggregate`‘annotate’和。示例代码如下:
    ```python
    result = Book.objects.aggregate(Avg("price"))
    ```
3. 聚合函数执行完成后,给这个聚合函数的值取个名字。取名字的规则,默认是`filed+__+聚合函数名字`形成的。比如以上代码形成的名字叫做`price__avg`。如果不想使用默认的名字,那么可以在使用聚合函数的时候传递关键字参数进去,参数的名字就是聚合函数执行完成的名字。实示例代码如下:
    ```python
    result = Book.objects.aggregate(avg=Avg("price"))
    ```
avg=为给这个Avg("price") 取得名字!

    以上传递了关键字参数`avg=Avg("price")`,那么以后`Avg`聚合函数执行完成的名字就叫做`avg`。
result 返回一个字典:{'avg': 97.25}
底层SQL语句:
[{'sql': 'SELECT @@SQL_AUTO_IS_NULL', 'time': '0.001'}, {'sql': 'SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED', 'time': '0.001'}, {'sql': 'SELECT AVG(`book`.`price`) AS `avg` FROM `book`', 'time': '0.463'}]
例如:
def index(request):
    # 获取所有图书的定价的平均价
    result = Book.objects.aggregate(avg=Avg("price"))
    print(result)
    # QuerySet
    # print(result.query)
    print(connection.queries) #打印SQL语句
    return HttpResponse("index")
4. `aggregate`:这个方法不会返回一个`QuerySet`对象,而是返回一个字典。这个字典中的key就是聚合函数的名字,值就是聚合函数执行后的结果。{'avg': 97.25}



5. `aggregate`和`annotate`的相同和不同:
    * 相同:这两个方法都可以执行聚合函数。
    * 不同:
        - `aggregate`返回的是一个字典,在这个字典中存储的是这个聚合函数执行的结果。而`annotate`返回的是一个`QuerySet`对象,并且会在查找的模型上添加一个聚合函数的属性。
        - `aggregate`不会做分组,而`annotate`会使用`group by`子句进行分组,只有调用了`group by`子句,才能对每一条数据求聚合函数的值。

例如:

def index2(request):
books = Book.objects.annotate(avg=Avg("bookorder__price"))  #bookorder 为Book模型所关联的Bookorder模型名小写,__ 双下划线为精确查找目标字典名字,精确查找可以省略exac
for book in books:  #annotate查出来是分组数据,需要遍历
    print('%s/%s'%(book.name,book.avg))
print(connection.queries)
return HttpResponse("index2")

点赞

3




登陆后方可评论