对中间模型 django 的一个字段进行注释
Posted
技术标签:
【中文标题】对中间模型 django 的一个字段进行注释【英文标题】:Annotate over a field of intermediate model django 【发布时间】:2018-12-04 22:19:11 【问题描述】:我有以下方案:
class User(AbstractUser):
pass
class Task(models.Model):
pass
class Contest(models.Model):
tasks = models.ManyToManyField('Task',
related_name='contests',
blank=True,
through='ContestTaskRelationship')
participants = models.ManyToManyField('User',
related_name='contests_participated',
blank=True,
through='ContestParticipantRelationship')
class ContestTaskRelationship(models.Model):
contest = models.ForeignKey('Contest', on_delete=models.CASCADE)
task = models.ForeignKey('Task', on_delete=models.CASCADE)
cost = models.IntegerField()
class ContestParticipantRelationship(models.Model):
contest = models.ForeignKey('Contest', on_delete=models.CASCADE)
user = models.ForeignKey('User', on_delete=models.CASCADE)
task = models.ForeignKey('Task', on_delete=models.CASCADE, related_name='contests_participants_relationship')
is_solved = models.BooleanField()
现在我得到了contest
对象,需要获取tasks
字段上的所有任务,用用户数注释的rach 解决了它。所以,我需要计算ContestParticipantRelationship
的数量,需要task
,需要contest
和is_solved
设置为True。如何进行这样的查询?
【问题讨论】:
User
可以解决一个任务多次次吗?
@WillemVanOnsem,不
【参考方案1】:
大概是这样的:
from django.db.models import IntegerField, Value, Sum
from django.db.models.functions import Cast, Coalesce
Task.objects.filter(
contests__contest=some_contest,
).annotate(
nsolved=Cast(Coalesce(
Sum('contests_participants_relationship__is_solved'), Value(0)
),IntegerField())
)
所以这里我们首先过滤任务的竞赛是some_contest
。接下来我们在is_solved
列上执行Sum(..)
。由于存在可能是NULL
的极端情况(如果没有用户进行尝试等),那么我们将其转换为0
,此外我们将其转换为IntegerField
,因为否则某些实例可能会使用True
和False
进行注释,以防零个或一个用户解决它。
【讨论】:
它不会遍历比赛的所有参与者,对布尔值求和吗?我一直在寻找一种通过过滤然后计数的解决方案 @NikitinRoman:好吧,因为每个用户最多只能解决一次,因此对于每个用户,最多有一个布尔值设置为 true。过滤计数方法将销毁没有用户设法解决的所有任务。所以0
s 不会出现在结果中。
并且在 SQL 中根本不存在布尔值:TRUE
是 1
的别名,FALSE
是 0
的别名。在 Python 中,布尔值确实存在,但它们是整数的子类(同样有 True-1/False-0
类比)。
我的意思是,如果在聚合之前进行一些过滤,会不会更快?
@NikitinRoman:这取决于过滤。通常如果没有索引存在。过滤应该更慢,因为这会破坏链接,从而导致显着的减速。但就像说的那样,这取决于索引是否到位,因为根据索引的不同,计数根本不属于枚举。以上是关于对中间模型 django 的一个字段进行注释的主要内容,如果未能解决你的问题,请参考以下文章