2013-05-01 99 views
2

我想添加到一个查询集在每个用户的页面请求计算出来的一些统计数据显示在一个大型的表。注释方法可能是最好的选择,但我坚持将创建的查询集合并为一个,以便在模板中进行更简单的操作。查询集类型是首选排序数据。django复杂queryset注释

以下是我的申请极其简化的原则。不能触摸模板和模型,因为它显然是我想要的结果。在这个例子中没有实现按列排序的数据。

下面是型号:

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()聚合函数不接受过滤器。

回答

1

对于这个需求,我会在轮询模型中再添加两个字段,它将使得更快的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() 

这也可以用信号来实现。

+0

我正在考虑像这样使用数据库,但希望避免这种情况。无论如何,这是最合理的解决方案。 – 2013-05-12 13:23:00

0

您可以随时在python中使用3个查询(仅在python中手动连接查询集)执行此操作,但以下是如何使用一个查询执行此操作: 如果需要注释的轮询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是聚合查询。 您可以访问查询查询集的方式如下:在聚合查询(QUERY2和QUERY3以上)

poll_list = Poll.objects.filter(...) 
poll_list.query.get_initial_alias() 
(query1,q1param) = poll_list.query.sql_with_params() 

你可以做到这一点也或者只是用手工写他们。

另请参阅http://www.reddit.com/r/django/comments/1dgz97/annotating_a_queryset_with_a_nontrivial_left/,其中执行了非平凡的查询集注释。

+0

这可能有效,但我宁愿避免纯粹的SQL。 – 2013-05-12 13:21:51