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