2009-12-05 79 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