我想在查询集中添加一些在每个用户的页面请求中计算的统计数据,以显示在一个大表中。 annotate方法可能是最好的选择,但我坚持将创建的查询集合并到单个方法中,以便在模板中更容易操作。查询集类型首选于排序数据。
以下是我申请的极其简化的原则。不得触摸模板和模型,因为它显然是我想要的结果。在此示例中未按列实现数据排序。
以下是模型:
class Poll(models.Model):
question = models.CharField(max_length=200, unique=True)
class Vote(models.Model):
poll = models.ForeignKey(Poll)
accept = models.BooleanField()
comment = models.CharField(max_length=200, unique=True)
censored = models.BooleanField()
以下是观点:
def summaryView(request):
…
contexte['poll_list'] = «insert code here»
…
return render_to_response('summary.html, contexte)
这是模板:
<table>
<thead>
<tr>
<th>
Poll question
</th>
<th>
Number of votes
</th>
<th>
Number of uncensored "yes" votes
</th>
<th>
Number of censored votes
</th>
</th>
</thead>
<tbody>
{% for poll in poll_list %}
<tr>
<td>
{{ poll.question }}
</td>
<td>
{{ poll.numUncensoredYesVotes }}
</td>
<td>
{{ poll.numCensoredVotes }}
</td>
</tr>
{% endfor %}
</tbody>
</table>
困难在于创建未经审查的“是”投票注释的数量。 Count()聚合函数不接受过滤器。
答案 0 :(得分:1)
对于这个要求,我会在Poll模型中添加两个字段,它将使更快的sql查询。通常在这些情况下,选择将比插入更频繁。因此,这将为您的项目带来更多性能提升。
from django.db import models
class Poll(models.Model):
question = models.CharField(max_length=200, unique=True)
num_censored_votes = models.PositiveIntegerField(default=0)
num_uncensored_yes_votes = models.PositiveIntegerField(default=0)
class Vote(models.Model):
poll = models.ForeignKey(Poll)
accept = models.BooleanField()
comment = models.CharField(max_length=200, unique=True)
censored = models.BooleanField()
def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
models.Model.save(self, force_insert, force_update, using, update_fields)
poll = self.poll
if self.censored:
poll.num_censored_votes += 1
poll.save()
elif self.accept:
poll.num_uncensored_yes_votes += 1
poll.save()
这也可以使用信号实现。
答案 1 :(得分:0)
你总是可以在python中使用3个查询(只需手动加入python中的查询集),但是这里有一个查询的方法: 如果您需要注释的Poll QuerySet是由query1生成的,则一个解决方案是
contexte['poll_list'] = Poll.objects.raw(
' select A.*, B.numcensoredvotes, C.numuncensoredyesvotes from
( query1 ) A left join (query2) B on A.id = B.poll_id
left join (query3) C on A.id = C.poll_id' )
其中query2和query3是聚合查询。 您可以通过以下方式访问查询集的查询:
poll_list = Poll.objects.filter(...)
poll_list.query.get_initial_alias()
(query1,q1param) = poll_list.query.sql_with_params()
您也可以为聚合查询(上面的query2和query3)执行此操作,或者只需手动编写它们。
另请参阅http://www.reddit.com/r/django/comments/1dgz97/annotating_a_queryset_with_a_nontrivial_left/以了解执行非平凡的查询集注释的相关场景。