Django को विशिष्ट क्रम में id की सरणी से एक QuerySet मिलता है


84

आप के लिए एक त्वरित heres:

मेरे पास आईडी की एक सूची है, जिसका उपयोग मैं एक क्वेरीसेट (या यदि आवश्यक हो तो सरणी) को वापस करने के लिए करना चाहता हूं, लेकिन मैं उस आदेश को बनाए रखना चाहता हूं।

धन्यवाद

जवाबों:


72

मुझे नहीं लगता कि आप डेटाबेस स्तर पर उस विशेष आदेश को लागू कर सकते हैं, इसलिए आपको इसके बजाय अजगर में करने की आवश्यकता है।

id_list = [1, 5, 7]
objects = Foo.objects.filter(id__in=id_list)

objects = dict([(obj.id, obj) for obj in objects])
sorted_objects = [objects[id] for id in id_list]

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


मैं उम्मीद कर रहा था कि यह मामला नहीं था :( साफ कोड के लिए धन्यवाद!
neolaser

3
बस विशाल प्रश्नों से सावधान रहें क्योंकि ऐसा करते समय आप मेमोरी में परिणाम जमा करेंगे।
जज।

14
हो सकता है कि खुद शब्दकोश का निर्माण करने के बजाय क्वेरीसेट इन_बल्क () पद्धति का उपयोग करें?
मैट ऑस्टिन

इसके साथ समस्या यह है कि अगर id_list में कोई ऑब्जेक्ट मौजूद नहीं है, तो यह एक त्रुटि फेंक देगा।
madprops

मेजर कॉम्प्रिहेंशन का इस्तेमाल क्यों नहीं करते?
wieczorek1990

186

Django 1.8 के बाद से, आप कर सकते हैं:

from django.db.models import Case, When

pk_list = [10, 2, 1]
preserved = Case(*[When(pk=pk, then=pos) for pos, pk in enumerate(pk_list)])
queryset = MyModel.objects.filter(pk__in=pk_list).order_by(preserved)

16
सर्वश्रेष्ठ उत्तर क्योंकि यह वास्तव में एक
क्वेरी

2
मुझे अभी भी लगता है कि django के Case Whenअंडर हैं!
बाबू

distinct()जब मैं खंड के साथ order_by मामले का उपयोग करने जा रहा हूं, लेकिन त्रुटि मिली। किसी भी समर्थन, कृपया।
एलक्विमिस्टा

SELECT DISTINCT ON expressions must match initial ORDER BY expressions- यहाँ त्रुटि संदेश है
elquimista

1
यह चयनित उत्तर होना चाहिए था।
सुबंगकर क्र्स

28

यदि आप in_bulk का उपयोग करके ऐसा करना चाहते हैं, तो आपको वास्तव में ऊपर दिए गए दो उत्तरों को मर्ज करने की आवश्यकता है:

id_list = [1, 5, 7]
objects = Foo.objects.in_bulk(id_list)
sorted_objects = [objects[id] for id in id_list]

अन्यथा परिणाम एक विशेष रूप से आदेशित सूची के बजाय एक शब्दकोश होगा।


1
यह एक बेहतर जवाब नहीं है।
टोनी

26

यहां डेटाबेस स्तर पर इसे करने का एक तरीका है। कॉपी पेस्ट से: blog.mathieu-leplatre.info :

MySQL :

SELECT *
FROM theme
ORDER BY FIELD(`id`, 10, 2, 1);

Django के साथ भी:

pk_list = [10, 2, 1]
ordering = 'FIELD(`id`, %s)' % ','.join(str(id) for id in pk_list)
queryset = Theme.objects.filter(pk__in=[pk_list]).extra(
           select={'ordering': ordering}, order_by=('ordering',))

PostgreSQL :

SELECT *
FROM theme
ORDER BY
  CASE
    WHEN id=10 THEN 0
    WHEN id=2 THEN 1
    WHEN id=1 THEN 2
  END;

Django के साथ भी:

pk_list = [10, 2, 1]
clauses = ' '.join(['WHEN id=%s THEN %s' % (pk, i) for i, pk in enumerate(pk_list)])
ordering = 'CASE %s END' % clauses
queryset = Theme.objects.filter(pk__in=pk_list).extra(
           select={'ordering': ordering}, order_by=('ordering',))

वाह। यह तीव्र है। धन्यवाद!
डैन गेल

इस उत्तर के लिए धन्यवाद।
सुबंगकर क्र।

9
id_list = [1, 5, 7]
objects = Foo.objects.filter(id__in=id_list)
sorted(objects, key=lambda i: id_list.index(i.pk))

1
कृपया यह बताते हुए कुछ पाठ जोड़ें कि यह कैसे काम करता है और यह ओपी की समस्या का समाधान क्यों करेगा। दूसरों को समझने में मदद करें।
एपीसी

सबसे बढ़िया उत्तर। धन्यवाद!
webjunkie

अच्छी तरह से काम करता है, हालांकि अतिरिक्त जानकारी का उपयोग कर सकता है
xtrinch

यह केवल ऑर्डर किए गए आईडी के लिए काम करेगा। क्या आप पुष्टि कर सकते हैं कि यह किसी भी क्रम का काम करेगा ... मुझे सच नहीं लगता।
Doogle
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.