2009-12-05 16 views
15

इस पर एक गिनती के साथ सेट क्वेरी में व्याख्या Django 1.1 में काम करने के लिए प्रतीत नहीं होता है (मेरा मानना ​​है कि यह एक सबक्वेरी की आवश्यकता होगी, इसलिए शीर्षक आता है)Django सबक्वेरी

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

मेरी क्वेरी सेट में आइटम हैं जिन्हें टैग किया गया है और टैग उपयोगकर्ताओं द्वारा पसंद किए जा सकते हैं, मैं गणना करना चाहता हूं कि उपयोगकर्ता ने टैग के माध्यम से सेट में प्रत्येक आइटम को कितनी बार पसंद किया था।

अतिरिक्त() का उपयोग किए बिना इस तरह की एक क्वेरी बनाने का कोई तरीका है?

धन्यवाद।

+0

क्या आपको एक त्रुटि संदेश मिलता है? क्या आप उन मॉडलों को प्रदान कर सकते हैं जिनके साथ आप काम कर रहे हैं? – cethegeek

+0

त्रुटि "अपवाद" क्यू 'ऑब्जेक्ट में कोई विशेषता नहीं है' विभाजन ', geradeausanwalt सही एकत्रीकरण funcs क्यू ऑब्जेक्ट्स तर्क के रूप में नहीं लेता है। उनके जवाब में मॉडल मेरे समान हैं। – Evgeny

उत्तर

10

add_aggregatedjango/db/models/sql/query.py के भीतर फ़ंक्शन को देखते हुए, क्वेरी ऑब्जेक्ट इनपुट मानों के रूप में स्वीकार नहीं किए जाएंगे।

दुर्भाग्य से, वर्तमान में 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() के माध्यम से परिभाषित क्षेत्रों पर एक क्वेरीसमूह व्याख्या नहीं कर सकते।

एक तो जैसे 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 की मात्रा को "कम करने" का कोई दूसरा तरीका है। शायद एसक्यूएल के भीतर सीधे related_name सुविधा का उपयोग करने के लिए कुछ दिलचस्प तरीका है?

1

यदि आप कच्चे एसक्यूएल को छोड़ने से बचना चाहते हैं, तो इस बिल्ली को त्वचा के लिए एक और तरीका मॉडल विधि का उपयोग करना होगा, जो आपको अपने टेम्पलेट्स में उपयोग करने के लिए मॉडल पर एक नई विशेषता देगा। Untested है, लेकिन पर अपने टैग कुछ इस तरह मॉडल काम करना चाहिए:

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

इस दृष्टिकोण का नकारात्मक पक्ष यह है कि यह डेटाबेस अधिक हिट कर सकता है:

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 

फिर अपने टेम्पलेट में आप की तरह कुछ का उपयोग कर सकते यदि आप एक बड़े पाश या कुछ में हैं। लेकिन आम तौर पर यह अच्छी तरह से काम करता है और संबंधित मॉडलों पर पूछताछ करने के लिए एनोटेट की अक्षमता के आसपास हो जाता है। और कच्चे एसक्यूएल का उपयोग करने से बचाता है।

+5

एनोटेशन के बराबर नहीं है, यह बहुत ही अनावश्यक है। – hcalves

संबंधित मुद्दे