Django笔记
操作数据库——ORM模型中的聚合函数查询
一、模型准备
from django.db import models
class GameCreator(models.Model):
username = models.CharField(max_length=200)
email = models.EmailField(unique=True)
class Game(models.Model):
name = models.CharField(max_length=100)
price = models.FloatField(default=0)
creator = models.ForeignKey(GameCreator, on_delete=models.CASCADE, related_name='games')
class Meta:
db_table = 'game_table'
在这个设置中,Game
模型通过 ForeignKey
关联到 GameCreator
模型,表示一个游戏创作者可以创建多个游戏,而每个游戏仅属于一个游戏创作者。
二、聚合函数
Django 提供了多种聚合函数,这些函数位于 django.db.models
模块中,用于执行各种统计计算。
2.1 Avg:平均值
知识点:Avg
用于计算某个字段的平均值。
示例:计算所有游戏的平均价格。
from django.db.models import Avg
average_price = Game.objects.aggregate(avg_price=Avg('price'))
print(f"Average game price: {average_price['avg_price']}")
2.2 Count:计数
知识点:Count
用于计算记录的数量。
示例:计算某个游戏创作者创建的游戏数量。
from django.db.models import Count
creator = GameCreator.objects.first() # 获取第一个游戏创作者
game_count = creator.games.count()
print(f"The first creator has created {game_count} games.")
或者使用 annotate()
来为每个游戏创作者标注其创建的游戏数量:
creators_with_game_count = GameCreator.objects.annotate(game_count=Count('games'))
for creator in creators_with_game_count:
print(f"{creator.username} has created {creator.game_count} games.")
2.3 Max 和 Min:最大值和最小值
知识点:Max
和 Min
分别用于找出某个字段的最大值和最小值。
示例:找出最贵和最便宜的游戏。
from django.db.models import Max, Min
max_price = Game.objects.aggregate(Max('price'))
min_price = Game.objects.aggregate(Min('price'))
print(f"Most expensive game price: {max_price['price__max']}")
print(f"Least expensive game price: {min_price['price__min']}")
2.4 Sum:总和
知识点:Sum
用于计算某个字段的总和。
示例:计算所有游戏的总价。
from django.db.models import Sum
total_price = Game.objects.aggregate(Sum('price'))
print(f"Total price of all games: {total_price['price__sum']}")
三、aggregate 和 annotate
使用 aggregate()
知识点:aggregate()
对整个 QuerySet 进行汇总计算,并返回一个包含汇总结果的字典。
示例:计算所有游戏的平均价格(已在 2.1 中展示),这里不再重复。
使用 annotate()
知识点:annotate()
为 QuerySet 中的每个对象添加汇总值作为新属性。
示例:为每个游戏创作者标注其创建的游戏数量(已在 2.2 中展示),这里提供另一个示例,计算每个游戏创作者创建的游戏的平均价格:
creators_with_avg_game_price = GameCreator.objects.annotate(avg_game_price=Avg('games__price'))
for creator in creators_with_avg_game_price:
print(f"{creator.username}'s games have an average price of {creator.avg_game_price}")
四、F表达式和Q表达式
使用 F
表达式
知识点:F
表达式允许您在不将值加载到 Python 内存的情况下引用模型字段,适用于批量更新或避免竞态条件。
示例:假设我们要增加每位游戏创作者所创建游戏的价格(例如,进行批量更新):
from django.db.models import F
# 增加每个游戏的价格10元
Game.objects.update(price=F('price') + 10)
使用 Q
表达式
知识点:Q
表达式允许您构建复杂的查询条件,特别是在需要使用 AND、OR 等逻辑运算符时。
示例:查找价格大于50的游戏或者名称包含“冒险”的游戏:
from django.db.models import Q
games = Game.objects.filter(Q(price__gt=50) | Q(name__contains='冒险'))
for game in games:
print(f"Game: {game.name}, Price: {game.price}")
复杂查询的例子,查找价格在50到100之间的游戏,并且排除名称为空的游戏:
games = Game.objects.filter(Q(price__gte=50) & Q(price__lte=100) & ~Q(name=''))
for game in games:
print(f"Game: {game.name}, Price: {game.price}")
小结
- 聚合函数 提供了强大的数据汇总能力,使得用户可以轻松地从数据库中提取统计信息。
aggregate()
方法用于对整个 QuerySet 进行汇总计算。annotate()
方法为每个 QuerySet 对象添加汇总值作为新属性,适用于需要为每个对象附加汇总信息的场景。F
表达式 可以用来优化数据库操作,特别是在执行批量更新时。Q
表达式 使得构建复杂查询条件成为可能,尤其是在需要使用 AND、OR 等逻辑运算符时。