对于下面的所有内容,我使用的是django1.9。你知道吗
我有一个Django模型,看起来像这样:
class Project(models.Model):
name = models.CharField()
task_count = models.FloatField()
requesters = models.ManyToManyField('Requester', through='ProjectRequester')
class ProjectRequester(models.Model):
project = models.ForeignKey('Project')
requester = models.ForeignKey('Requester')
class Requester(models.Model):
username = models.CharField()
我有一个表单,允许用户获取所有项目的总任务数,或者按名称或请求者对任务数进行分组。如果你按名字分组的话,这完全可以。你会得到一个类似这样的查询集:
qs = Project.objects.select_related().values('name')
qs = qs.annotate(task_count=models.Sum('task_count'))
生成的SQL与您预期的完全一样,类似于:
SELECT SUM(Project.task_count) FROM Project GROUP BY Project.Name;
然而,由于多对多与请求者连接,当您按请求者透视时,任何有1个以上请求者的项目都会重复计算其任务。这是:
qs = Project.objects.select_related().values('requesters__username')
qs = qs.annotate(task_count=models.Sum('task_count'))
结果是:
SELECT SUM(Project.task_count) FROM Project
LEFT OUTER JOIN ProjectRequester ON ProjectRequester.ProjectId=Project.Id
LEFT OUTER JOIN Requester ON Requester.Id=ProjectRequester.RequesterId
GROUP BY Requester.Username;
我绝对不想放弃使用原始sql,原因有很多。因此,我最初的想法是将请求者的数量存储为项目模型(requester_count = models.FloatField()
)上的一个字段,当项目加载到表中时,该字段将自动填充。这样,我可以将上面创建的查询集的第二行更改为:
task_count = models.Sum(models.ExpressionWrapper(
models.F('task_count') / models.F('requester_count')
qs = qs.annotate(task_count=task_count)
这将产生所需的结果:
SELECT SUM(Project.task_count / Project.requester_count) FROM Project
LEFT OUTER JOIN ProjectRequester ON ProjectRequester.ProjectId=Project.Id
LEFT OUTER JOIN Requester ON Requester.Id=ProjectRequester.RequesterId
GROUP BY Requester.Username;
耶!然而,这里实际上还有很多其他的东西(大约20种其他方法可以实际透视,加上通过这些字段的任意组合进行过滤的能力),所以这并不像简单地添加if pivot == 'name', use regular sum annotation, else use sum divided by requester count
那么简单(因为如果左外连接没有发生,使用第二个注释将不会产生正确数量的任务)。你知道吗
这就引出了我的问题:有没有什么方法可以强制Django总是将左外连接添加到ProjectRequester表中,即使该表中没有filter或groupby?这样,我就可以简单地除以请求者的计数,而不必考虑数据透视或过滤器,这样就可以算出结果。你知道吗
提前谢谢。你知道吗
目前没有回答
相关问题 更多 >
编程相关推荐