2009-12-05 13 views
15

これはdjango 1.1で動作していないようです(これはサブクエリが必要だと思うので、タイトルになります)サブクエリにカウントを設定したDjango注釈クエリセット

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

タグ付きのクエリセットにはアイテムがあり、私はユーザーがタグを使ってセット内の各アイテムを何度もお気に入りにした回数を計算したいと思います。

はextra()を使わずにこのようなクエリを作成する手段ですか?

ありがとうございました。

+0

エラーメッセージが表示されますか?あなたが働いているモデルを提供できますか? – cethegeek

+0

エラーがgeradeausanwaltが右集約のfuncsは、引数としてQオブジェクトを取ることはありませんで、「例外 『Q』オブジェクトが 『スプリット』を何の属性を持っていない」です。彼の答えのモデルは私のものに似ています。 – Evgeny

答えて

10

、クエリオブジェクトは、入力値として受け付けられません。

は残念ながら、特に、現在、さらに何らかの形で濾過される1クエリセットに相当するものに注釈を付ける/集約するジャンゴ内には直接的な方法はありません。

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()経由で定義されたフィールド上のクエリセットに注釈をつけることができません。次のモデルを想定し

一つは、そうのようviews.pyにSQLにドロップすることができます:

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の量を減らす別の方法があるかどうか不思議です。たぶん、related_name機能をSQL内で直接利用する興味深い方法がありますか?

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

関連する問題