2009-12-05 80 views
15

这是一个计数设定似乎并不在Django 1.1上班(我相信这将需要一个子查询,因此而来的标题)Django的注释查询与子查询

qs.annotate(interest_level= \ 
      Count(Q(tags__favoritedtag_set__user=request.user)) 
      ) 

有我的查询组项目哪些被标记并且标签可以被用户所偏好,我想计算一次用户通过标签对该组中的每个项目进行了收费的次数。

有没有一种方法来构建这样的查询,而不使用extra()?

谢谢。

+0

您是否收到错误讯息?你能提供你正在使用的模型吗? – cethegeek 2009-12-05 04:35:38

+0

错误是“异常”Q“对象没有属性”分裂“”,geradeausanwalt是正确的聚合funcs不采取Q对象作为参数。他的答案中的模型与我的相似。 – Evgeny 2009-12-06 19:57:20

回答

10

查看django/db/models/sql/query.py中的add_aggregate函数,查询对象将不会被接受为输入值。

不幸的是,在Django中目前没有直接的方式来聚合/注释什么相当于一个查询集,特别是没有一个额外的过滤器。

假设以下型号:

class Item(models.Model): 
    name = models.CharField(max_length=32) 

class Tag(models.Model): 
    itemfk = models.ForeignKey(Item, related_name='tags') 
    name = models.CharField(max_length=32) 

class FavoritedTag(models.Model): 
    user = models.ForeignKey(User) 
    tag = models.ForeignKey(Tag) 

而且,你不能批注通过.extra()定义的字段的查询集。

人们可以拖放到SQL中views.py像这样:

from testing.models import Item, Tag, FavoritedTag 
from django.shortcuts import render_to_response 
from django.contrib.auth.decorators import login_required 
from django.utils.datastructures import SortedDict 

@login_required 
def interest_level(request): 
    ruid = request.user.id 

    qs = Item.objects.extra(
     select = SortedDict([ 
      ('interest_level', 'SELECT COUNT(*) FROM testing_favoritedtag, testing_tag \ 
      WHERE testing_favoritedtag.user_id = %s \ 
      AND testing_favoritedtag.tag_id = testing_tag.id \ 
      AND testing_tag.itemfk_id = testing_item.id'), 
     ]), 
     select_params = (str(ruid),) 
    ) 

    return render_to_response('testing/interest_level.html', {'qs': qs}) 

模板:

{% for item in qs %} 
    name: {{ item.name }}, level: {{ item.interest_level }}<br> 
{% endfor %} 

我测试了使用MySQL5的。因为我不是SQL专家,所以我很好奇如何在这里优化,或者如果有另一种方法来“减少”SQL的数量。也许有一些有趣的方式直接在SQL中使用related_name功能?

1

如果您想要避免丢弃原始SQL,另一种方法来使用这个猫,可以使用模型方法,然后该方法会为您在模板中使用的模型提供一个新属性。未经检验的,但这样的事情在你的标签模型应该工作:

class Tag(models.Model): 
    itemfk = models.ForeignKey(Item, related_name='tags') 
    name = models.CharField(max_length=32) 

    def get_favetag_count(self): 
     """ 
     Calculate the number of times the current user has favorited a particular tag 
     """ 

     favetag_count = FavoritedTag.objects.filter(tag=self,user=request.user).count() 
     return favetag_count 

然后在你的模板,你可以使用类似:

{{tag}} ({{tag.get_favetag_count}}) 

这种方法的缺点是,它可以访问数据库更如果你在一个大循环或什么东西。但总的来说,它运行良好,避免了注释无法在相关模型上执行查询。并避免必须使用原始SQL。

+5

根本不等同于注释,这非常无益。 – hcalves 2012-11-12 20:40:40