2013-02-12 53 views
10

मुझे एक साधारण संदेश प्रणाली में उपयोगकर्ता गतिविधि के सारांश के साथ एक टेम्पलेट भरना होगा। प्रत्येक संदेश प्रेषक के लिए, मुझे भेजे गए संदेशों की संख्या और विशिष्ट प्राप्तकर्ताओं की संख्या चाहिए।SQL COUNT का Django ORM संस्करण (DISTINCT <column>)

class Message(models.Model): 
    sender = models.ForeignKey(User, related_name='messages_from') 
    recipient = models.ForeignKey(User, related_name='messages_to') 
    timestamp = models.DateTimeField(auto_now_add=True) 

यहाँ कैसे मैं एसक्यूएल में ऐसा करेंगे::

यहाँ मॉडल का एक सरलीकृत संस्करण है

SELECT sender_id, COUNT(id), COUNT(DISTINCT recipient_id) 
    FROM myapp_messages 
    GROUP BY sender_id; 

मैं ORM प्रश्नों में एकत्रीकरण पर दस्तावेज़ीकरण के माध्यम से पढ़ने किया गया है, और हालांकि एनोटेट() पहले COUNT कॉलम को संभाल सकता है, मुझे COUNT (DISTINCT) परिणाम प्राप्त करने का कोई तरीका नहीं दिखाई देता है (यहां तक ​​कि अतिरिक्त (select = {}) काम नहीं कर रहा है, हालांकि ऐसा लगता है कि ऐसा होना चाहिए)। क्या इसका अनुवाद डीजेगो ओआरएम क्वेरी में किया जा सकता है या क्या मुझे कच्चे एसक्यूएल के साथ रहना चाहिए?

+0

[ ' .distinct() '] (https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.distinct) फ़िल्टर कॉम हो सकता है आसान में ई। –

+0

यदि हम COUNT (DISTINCT प्राप्तकर्ता_आईडी) को अनदेखा करते हैं तो यह एनोटेट और गणना फ़ंक्शन का उपयोग करके बहुत सरल है। यहां, django की विशिष्ट() मदद नहीं करता है। मुझे नहीं लगता कि इन दो चीजों (एनोटेट और विशिष्ट) को एक साथ एकीकृत करना संभव है। मुझे लगता है कि आपको दो प्रश्न लिखना है। – jurgenreza

उत्तर

8

आप वास्तव में विशिष्ट का उपयोग करें और के रूप में इस जवाब पर देखा, एक साथ भरोसा कर सकते हैं: https://stackoverflow.com/a/13145407/237091

आपके मामले में:

SELECT sender_id, COUNT(id), COUNT(DISTINCT recipient_id) 
FROM myapp_messages 
GROUP BY sender_id; 

बन जाएगा:

Message.objects.values('sender').annotate(
    message_count=Count('sender'), 
    recipient_count=Count('recipient', distinct=True)) 
4
from django.db.models import Count 

messages = Message.objects.values('sender').annotate(message_count=Count('sender')) 

for m in messages: 
    m['recipient_count'] = len(Message.objects.filter(sender=m['sender']).\ 
           values_list('recipient', flat=True).distinct()) 
+0

धन्यवाद! क्या मैं समझने में सही हूं कि इसका मतलब है कि संदेश प्रेषक (प्लस वन) के रूप में कई डेटाबेस प्रश्न होंगे? – nephtes

+0

@nephtes हां। असल में मुझे नहीं लगता कि गणना() के अंदर अलग() का उपयोग करने का कोई तरीका है। शायद, आप कच्चे वर्ग के साथ बेहतर हैं। मुझे लगता है कि यह django के साथ ऐसा करने का सबसे अच्छा तरीका है, जब तक कि अन्य लोग एक बेहतर विचार के साथ आते हैं! – jurgenreza

+1

@jurgenreza (मुझे पता है कि यह पोस्ट पुराना है लेकिन ...) मेरा मानना ​​है कि एक बेहतर तरीका अतिरिक्त उपयोग करना होगा: Message.objects.filter (...)। अतिरिक्त ({'प्राप्तकर्ता_count': 'COUNT (DISTINCT recipient_id) '})। मान (' recipient_count ')। अतिरिक्त पर डॉक्स: https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.extra – paperreduction