Django में DISTINCT व्यक्तिगत कॉलम चुनें?


93

मुझे उत्सुकता है अगर Django में क्वेरी करने का कोई तरीका है जो कि SELECT * FROM...नीचे नहीं है। मैं SELECT DISTINCT columnName FROM ...इसके बजाय " " करने की कोशिश कर रहा हूं ।

विशेष रूप से मेरे पास एक मॉडल है जो दिखता है:

class ProductOrder(models.Model):
   Product  = models.CharField(max_length=20, promary_key=True)
   Category = models.CharField(max_length=30)
   Rank = models.IntegerField()

जहां Rankएक के भीतर एक पद है Category। मैं उस श्रेणी के भीतर प्रत्येक रैंक पर कुछ ऑपरेशन करने वाले सभी श्रेणियों पर पुनरावृति करने में सक्षम होना चाहता हूं।

मैं पहले सिस्टम में सभी श्रेणियों की सूची प्राप्त करना चाहता हूं और फिर उस श्रेणी के सभी उत्पादों के लिए क्वेरी करता हूं और तब तक दोहराता हूं जब तक कि हर श्रेणी संसाधित न हो जाए।

मैं कच्ची एसक्यूएल से बचना चाहता हूं, लेकिन अगर मुझे वहां जाना है, तो यह ठीक रहेगा। हालांकि मैंने पहले Django / Python में कच्चे SQL को कोडित नहीं किया है।

जवाबों:


185

डेटाबेस से अलग कॉलम नामों की सूची प्राप्त करने का एक तरीका यह है कि distinct() किसके साथ संयोजन में उपयोग किया जाए values()

आपके मामले में आप विभिन्न श्रेणियों के नाम प्राप्त करने के लिए निम्नलिखित कर सकते हैं:

q = ProductOrder.objects.values('Category').distinct()
print q.query # See for yourself.

# The query would look something like
# SELECT DISTINCT "app_productorder"."category" FROM "app_productorder"

यहां कुछ बातें याद रखने लायक हैं। सबसे पहले, यह एक वापसी करेगा ValuesQuerySetजो एक से अलग व्यवहार करता है QuerySet। जब आप कहते हैं, का पहला तत्व q(ऊपर) आपको एक शब्दकोश मिलेगा , तो इसका उदाहरण नहीं ProductOrder

दूसरा, यह डॉक्स में चेतावनी नोट को पढ़ने के बारे में एक अच्छा विचार है distinct()। उपरोक्त उदाहरण काम करेगा, लेकिन सभी के संयोजन distinct()और values()नहीं हो सकता है।

पुनश्च : एक मॉडल में फ़ील्ड के लिए निचले मामलों के नामों का उपयोग करना एक अच्छा विचार है । आपके मामले में इसका मतलब होगा कि आपके मॉडल को फिर से लिखना जैसा कि नीचे दिखाया गया है:

class ProductOrder(models.Model):
    product  = models.CharField(max_length=20, primary_key=True)
    category = models.CharField(max_length=30)
    rank = models.IntegerField()

1
विधि नीचे वर्णित अब Django 1.4 में उपलब्ध है और अच्छा होगा यदि आप क्षेत्र के साथ ProductOrder उदाहरण की जरूरत अलग ;-) बारे में पता है
जोनाथन Liuti

60

यह वास्तव में काफी सरल है अगर आप PostgreSQL का उपयोग कर रहे हैं , तो बस उपयोग करें distinct(columns)( प्रलेखन )।

Productorder.objects.all().distinct('category')

ध्यान दें कि यह फीचर 1.4 के बाद से Django में शामिल किया गया है


@lazerscience, @Manoj गोविंदन: मुझे क्षमा करें, आप सही हैं। ऐसा लगता है कि मैंने उस सुविधा को जोड़ने के लिए Django को पैच किया है। मैंने
वोल्फ ऑक्ट

3
यह अब Django SVN में है और Django 1.4 में
होगा

14
नोट: जब तक आप PostgreSQL का उपयोग नहीं कर रहे हैं, आप एक तर्क () को अलग नहीं दे सकते। ऊपर स्वीकार किए गए समाधान के साथ सबसे अच्छी छड़ी।
मार्क चेकरियन 21

परीक्षणों में, यह can_distinct_on_fieldsपोस्टग्रेज-ओनली प्रतीत होता है
स्काइलर सेवलैंड

3
प्लस 1, लेकिन all()यहां आवश्यक नहीं है
एंटनी हैचकिंस

17

अन्य उत्तर ठीक हैं, लेकिन यह एक छोटा क्लीनर है, इसमें यह केवल उन मूल्यों को देता है जैसे कि आप DISTINCT क्वेरी से प्राप्त करेंगे, बिना Django के कोई क्रॉफ्ट।

>>> set(ProductOrder.objects.values_list('category', flat=True))
{u'category1', u'category2', u'category3', u'category4'}

या

>>> list(set(ProductOrder.objects.values_list('category', flat=True)))
[u'category1', u'category2', u'category3', u'category4']

और, यह PostgreSQL के बिना काम करता है।

यह .distinct () का उपयोग करने की तुलना में कम कुशल है, यह मानते हुए कि आपके डेटाबेस में DISTINCT एक अजगर से तेज है set, लेकिन यह शेल के आसपास नूडलिंग के लिए बहुत अच्छा है।


values_listDISTINCTsql क्वेरी में नहीं डाला जाता है, इसलिए यदि ऐसा होता तो कई मान आ जाते।
mehmet

12

उस फ़ील्ड के साथ उपयोगकर्ता क्रम, और फिर अलग करते हैं।

ProductOrder.objects.order_by('category').values_list('category', flat=True).distinct()
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.