反向查询和反向引用
- 反向查询: 将模型名字小写化。 比如
article_in。可以通过related_query_name来指定名字。 - 反向引用: 将模型名字小写化,加上
_set。比如article_set,可以通过related_name来指定自己的方式。
聚合函数
- 如果你用原生
SQL,则可以使用聚合函数来提取数据。比如提取某个商品销售的数量,那么可以使用Count,如果想要知道商品销售的平均价格,那么可以使用Avg。 - 聚合函数不能单独执行,需要放在一些可以执行聚合函数的方法下面中去执行。比如
aggregate方法来实现的。 - 聚合函数执行完毕之后,
Django默认给聚合函数的值取个名字。命名规则是filed名+__+聚合函数名。 - 在讲解这些聚合函数的用法的时候,都是基于以下的模型对象来实现的。
from django.db import modelsclass 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 Me ta:db_table = 'book'class BookOrder(models.Model):"""图书订单模型"""book = models.ForeignKey("Book",on_delete=models.CASCADE)price = models.FloatField()class Meta:db_table = 'book_order'
Avg
求平均值。比如想要获取所有图书的价格平均值。那么可以使用以下代码实现。
from django.db.models import Avgresult = Book.objects.aggregate(Avg('price'))print(result)
以上的打印结果是:
{"price__avg":23.0}
其中price__avg的结构是根据field__聚合函数名规则构成的。如果想要修改默认的名字,那么可以将Avg赋值给一个关键字参数。示例代码如下:
from django.db.models import Avgresult = Book.objects.aggregate(my_avg=Avg('price'))print(result)
那么以上的结果打印为:
{"my_avg":23}
Count
获取指定的对象的个数。示例代码如下:
from django.db.models import Countresult = Book.objects.aggregate(book_num=Count('id'))
以上的result将返回Book表中总共有多少本图书。Count类中,还有另外一个参数叫做distinct,默认是等于False,如果是等于True,那么将去掉那些重复的值。比如要获取作者表中所有的不重复的邮箱总共有多少个,那么可以通过以下代码来实现:
from djang.db.models import Countresult = Author.objects.aggregate(count=Count('email',distinct=True))
Max和Min
获取指定对象的最大值和最小值。比如想要获取Author表中,最大的年龄和最小的年龄分别是多少。那么可以通过以下代码来实现:
from django.db.models import Max,Minresult = Author.objects.aggregate(Max('age'),Min('age'))
如果最大的年龄是88,最小的年龄是18。那么以上的result将为:
{"age__max":88,"age__min":18}
Sum
求指定对象的总和。比如要求图书的销售总额。那么可以使用以下代码实现:
from djang.db.models import Sumresult = Book.objects.annotate(total=Sum("bookstore__price")).values("name","total")
以上的代码annotate的意思是给Book表在查询的时候添加一个字段叫做total,这个字段的数据来源是从BookStore模型的price的总和而来。values方法是只提取name和total两个字段的值。
更多的聚合函数请参考官方文档:https://docs.djangoproject.com/en/2.0/ref/models/querysets/#aggregation-functions
aggregate和annotate的区别
aggregate:返回使用聚合函数后的字段和值。返回一个dictannotate:返回一个QuerySet。在原来模型字段的基础之上添加一个使用了聚合函数的字段,并且在使用聚合函数的时候,会使用当前这个模型的主键进行分组(group by)。
比如以上Sum的例子,如果使用的是annotate,那么将在每条图书的数据上都添加一个字段叫做total(这个字段看你自己设不设置,不设置就使用默认的Field__聚合方式名),计算这本书的销售总额。
而如果使用的是aggregate,那么将求所有图书的销售总额。- 都可以在任何的
QuerySet对象调用
比如要获取2018年度的销售总额,可以先过滤年份,再求聚合函数BookOrder.object.filter(create_time__year=2018).aggregate(total=Sun('price'))
