Django使用子查询计数注释查询集 [英] Django annotate query set with a count on subquery

查看:107
本文介绍了Django使用子查询计数注释查询集的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这在django 1.1中似乎不起作用(我相信这将需要一个子查询,因此是标题)

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

我的查询集中有些项目被标记,标签可以由用户收藏,我想计算一个用户通过标签收集了每个项目的多少次。



有没有使用extra()来构造这样的查询的方法?



谢谢。

解决方案

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



不幸的是,目前Django中没有直接的方式聚合/注释什么是查询集,特别是没有一个额外被过滤的东西。



假设有以下模型:

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

class标签(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()定义的字段上注释查询集。



可以在 views.py 中放入SQL,如下所示:


$ b从django.shortcuts导入项目,标签,FavoritedTag
导入render_to_response
从django.contrib.auth.decorators导入login_required $ b $ $ $ $ $ $ $ b从django.utils.datastructures import SortedDict

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

qs = Item.objects.extra(
sel ect = 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 test_tag.itemfk_id = testing_item.id'),
]),
select_params =(str(ruid))


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

模板:

  {%for qs%} 
name:{{item.name}},级别:{ {item.interest_level}}< br>
{%endfor%}

我使用MySQL5进行了测试。既然我不是SQL专家,那么对于这里如何进行优化,或者还有另一种方式来减少SQL的数量,我会很好奇。也许有一些有趣的方式可以在SQL中直接使用 related_name 功能?


This doesn't seem to work in django 1.1 (I believe this will require a subquery, therefore comes the title)

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

There are items in my query set which are tagged and tags can be favorited by users, I would like to calculate how many times a user had favorited each item in the set via tags.

is there a way to construct a query like this without using extra()?

Thanks.

解决方案

Looking at the add_aggregate function within django/db/models/sql/query.py, query objects will not be accepted as input values.

Unfortunately, there is currently no direct way within Django to aggregate/annotate on what amounts to a queryset, especially not one that is additionally filtered somehow.

Assuming the following models:

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)

Also, you cannot annotate a queryset on fields defined via .extra().

One could drop into SQL in views.py like so:

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

Template:

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

I tested this using MySQL5. Since I'm no SQL expert though, I'd be curious as to how to optimize here, or if there is another way to "lessen" the amount of SQL. Maybe there is some interesting way to utilize the related_name feature here directly within SQL?

这篇关于Django使用子查询计数注释查询集的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆