2

我想将在每个用户的页面请求中计算的一些统计数据添加到查询集中,以显示在一个大表中。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() 聚合函数不接受过滤器。

4

2 回答 2

1

For this requirement I would add two more fields in the Poll models it will make faster sql queries. Normally in theses cases selection will be more frequent than insertion. So this will give more performance improvement to your project.

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()

This can be also implemented using signals.

于 2013-05-01T23:45:10.440 回答
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/以了解执行非平凡查询集注释的相关场景。

于 2013-05-01T22:45:27.973 回答