Django 查询优化计算相关字段的相关字段
Django Query Optimization count a related field of a related field
我正在为我的兄弟会编写一个 Django 应用程序来对 rushees 进行投票,我正在尝试优化我的一个查询,该查询计算选票并打印出计数以及来自他们应用程序的信息。 Django-debug 工具栏告诉我有很多重复的查询
(为清楚起见,以下代码已被截断和编辑)
models.py
votechoices = ((1, "Yes"),(2, "No"),(3, "Abstain"))
class Vote(models.Model):
brother = models.ForeignKey(Brother)
rushee = models.ForeignKey(Rushee)
choice = models.IntegerField(choices=votechoices, default=3)
class Rushee(models.Model):
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=40)
#ETC, ETC
class Application(models.Model):
rushee = models.ForeignKey(Rushee)
address = models.CharField(max_length=200)
cellphone = models.CharField(max_length=30)
#ETC, ETC
views.py
def getvotecount(request):
# get all the applications ( we only vote on people who have an application)
applicationobjs = Application.objects.select_related('rushee').all()
# iterate through the applications and count the votes
for app in applicationobjs.iterator():
#>>>> This Query below is a seperate query everytime! So that means that If we have 200 rushees there are 200 queries!
counts = Vote.objects.filter(rushee=app.rushee).values('choice').annotate(count=Count('choice'))
votesfor = sum([x['count'] for x in counts if x['choice'] == 1])
votesagainst = sum([x['count'] for x in counts if x['choice'] == 2])
result = [app.rushee.first_name + ' ' + app.rushee.last_name,
app.address, app.cellphone,
str(votesfor), str(votesagainst),]
# Uninteresting stuff below that will group together and return the results
我正在尝试优化标记为 (>>>>) 的视图中的查询,这样我就可以 return 每个 rushee 的票数,而无需每次 运行 单独查询!
补充信息:
sqlite 后端, rushies 比applications 多很多, 我们只投票给有应用程序的rushees
您可以使用 conditional expressions 在一个查询中完成所有这些:
from django.db.models import Case, IntegerField, Sum, When
rushees = Rushee.objects.annotate(
votes_for=Sum(
Case(
When(vote=1, then=1),
default=0,
output_field=IntegerField(),
)
),
votes_against=Sum(
Case(
When(vote=2, then=1),
default=0,
output_field=IntegerField(),
)
)
)
结果查询集中的 rushees
将有一个 votes_for
和 votes_against
属性,每个都有计数。这假设没有针对 rushees
没有申请的投票记录 - 但如果有,那么您可以轻松过滤掉那些。
我正在为我的兄弟会编写一个 Django 应用程序来对 rushees 进行投票,我正在尝试优化我的一个查询,该查询计算选票并打印出计数以及来自他们应用程序的信息。 Django-debug 工具栏告诉我有很多重复的查询
(为清楚起见,以下代码已被截断和编辑)
models.py
votechoices = ((1, "Yes"),(2, "No"),(3, "Abstain"))
class Vote(models.Model):
brother = models.ForeignKey(Brother)
rushee = models.ForeignKey(Rushee)
choice = models.IntegerField(choices=votechoices, default=3)
class Rushee(models.Model):
first_name = models.CharField(max_length=40)
last_name = models.CharField(max_length=40)
#ETC, ETC
class Application(models.Model):
rushee = models.ForeignKey(Rushee)
address = models.CharField(max_length=200)
cellphone = models.CharField(max_length=30)
#ETC, ETC
views.py
def getvotecount(request):
# get all the applications ( we only vote on people who have an application)
applicationobjs = Application.objects.select_related('rushee').all()
# iterate through the applications and count the votes
for app in applicationobjs.iterator():
#>>>> This Query below is a seperate query everytime! So that means that If we have 200 rushees there are 200 queries!
counts = Vote.objects.filter(rushee=app.rushee).values('choice').annotate(count=Count('choice'))
votesfor = sum([x['count'] for x in counts if x['choice'] == 1])
votesagainst = sum([x['count'] for x in counts if x['choice'] == 2])
result = [app.rushee.first_name + ' ' + app.rushee.last_name,
app.address, app.cellphone,
str(votesfor), str(votesagainst),]
# Uninteresting stuff below that will group together and return the results
我正在尝试优化标记为 (>>>>) 的视图中的查询,这样我就可以 return 每个 rushee 的票数,而无需每次 运行 单独查询!
补充信息: sqlite 后端, rushies 比applications 多很多, 我们只投票给有应用程序的rushees
您可以使用 conditional expressions 在一个查询中完成所有这些:
from django.db.models import Case, IntegerField, Sum, When
rushees = Rushee.objects.annotate(
votes_for=Sum(
Case(
When(vote=1, then=1),
default=0,
output_field=IntegerField(),
)
),
votes_against=Sum(
Case(
When(vote=2, then=1),
default=0,
output_field=IntegerField(),
)
)
)
结果查询集中的 rushees
将有一个 votes_for
和 votes_against
属性,每个都有计数。这假设没有针对 rushees
没有申请的投票记录 - 但如果有,那么您可以轻松过滤掉那些。