2013-06-30 19 views
7

मेरे पास Django (Postgres के साथ) में निम्न मॉडल स्कीमा है।Django: कई टोनी क्षेत्रों के आईडी पुनर्प्राप्त करने के लिए

class A(Models.model): 
    related = models.ManyToManyField("self", null=True) 

को देखते हुए एक के एक क्वेरीसमूह, मैं एक शब्दकोश मानचित्रण अधिक तेज़ी से related उदाहरणों में से id रों की एक सूची के लिए क्वेरीसमूह में A के प्रत्येक उदाहरण के वापस जाने के लिए संभव के रूप में चाहते हैं।

मैं निश्चित रूप से प्रत्येक ए के माध्यम से पुनरावृत्त कर सकता हूं और संबंधित क्षेत्र से पूछताछ कर सकता हूं, लेकिन क्या यह एक और इष्टतम तरीका है?

+0

क्या आपको कभी इसका समाधान मिला? – cazgp

उत्तर

8

आपके अनुसार तीन उदाहरण हैं। आप परिणामों को पुनर्प्राप्त करने के लिए values_list विधि का उपयोग कर सकते हैं और इस परिणाम से केवल उनके related उदाहरणों की आईडी प्राप्त हो सकती है। मैं अपने फ़िल्टर होने के लिए pk फ़ील्ड का उपयोग करता हूं क्योंकि मुझे आपकी योजना नहीं पता है, लेकिन आप कुछ भी उपयोग कर सकते हैं, बस QuerySet होना चाहिए।

>>> result = A.objects.filter(pk=1) 
>>> result.values('related__id') 
[{'id': 2}, {'id': 3}] 
>>> result.values_list('related__id') 
[(2,), (3,)] 
>>> result.values_list('related__id', flat=True) 
[2, 3] 
+1

यही वह है जो मैं कर रहा हूं, लेकिन समस्या यह है कि मुझे एक से अधिक 'pk' (उदा।' एबजेक्ट्सफिल्टर (pk__in = [1,2,6]) पर फ़िल्टर करने की आवश्यकता है। मुझे सूचियों की एक सूची चाहिए, जहां nth आंतरिक सूची यहां 'value_list' की तरह है, लेकिन nth 'pk' से संबंधित है। –

+0

आप example.related.values ​​('id', flat = True) भी कर सकते हैं, यदि आपके पास पहले से ही एक मॉडल उदाहरण है। – alexcasalboni

0

आप इस तरह बहुत करीब प्राप्त कर सकते हैं:

qs = A.objects.prefetch_related(Prefetch(
         'related', 
         queryset=A.objects.only('pk'), 
         to_attr='related_insts')).in_bulk(my_list_of_pks) 

यह तो आप इस प्रकार के माध्यम से पुनरावृति कर सकते हैं, उदाहरण के लिए ही वर्तमान वस्तु के पीकेएस से एक मानचित्रण दे देंगे:

for pk, inst in qs.iteritems(): 
    related_ids = (related.pk for related in inst.related_insts) 

या एक उदाहरण दिया, तो आप ऐसा तरह एक तेजी से देखने कर सकते हैं:

related_ids = (related.pk for related in qs[instance.pk]). 

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

qs = A.objects.prefetch_related(Prefetch(
     'related', 
     queryset=A.objects.only('pk'), 
     to_attr='related_insts')).filter(pk__in=my_list_of_pks) 
for inst in qs: 
    related_ids = (related.pk for related in inst.related_insts) 

आप केवल db से पीकेएस खींचने के लिए only के उपयोग को ध्यान में रखना कर सकते हैं। values के उपयोग की अनुमति देने के लिए open ticket है और प्रीफ़ेच प्रश्नों में values_list (मुझे लगता है)। यह आपको निम्नलिखित करने की अनुमति देगा।

qs = A.objects.prefetch_related(Prefetch(
     'related', 
     queryset=A.objects.values_list('pk', flat=True), 
     to_attr='related_ids')).filter(pk__in=my_list_of_pks) 
for inst in qs: 
    related_ids = inst.related_ids 

आप निश्चित रूप से आगे प्राथमिक क्वेरीसमूह पर qs.only('related_insts') का उपयोग करके अनुकूलन कर सकता है, उदाहरण के लिए, लेकिन सुनिश्चित करें कि आप instances-- वे अनिवार्य रूप से सिर्फ महंगा कंटेनर अपने related_ids धारण करने के लिए कर रहे हैं इन के साथ कुछ नहीं कर रहे हैं।

मेरा मानना ​​है कि यह अब तक का सर्वोत्तम है (कस्टम प्रश्नों के बिना)। वास्तव में आप क्या चाहते हैं, दो बातें आवश्यक हैं प्राप्त करने के लिए:

  1. विशेषता के ऊपर लागू किया गया है
  2. values_list प्रीफ़ेच to_attr के साथ काम करने की तरह यह एनोटेशन के लिए करता है।
जगह में इन दो चीजों के साथ

(और ऊपर के उदाहरण जारी) तुम कर सकते हो निम्नलिखित आप वास्तव में क्या अनुरोध किया पाने के लिए: लेकिन,

d = qs.values_list('related_ids', flat=True).in_bulk() 
for pk, related_pks in d: 
    print 'Containing Objects %s' % pk 
    print 'Related objects %s' % related_pks 
# And lookups 
print 'Object %d has related objects %s' % (20, d[20]) 

मैं कुछ विवरण दूर छोड़ दिया कि चीज़ें समझा यह दस्तावेज़ीकरण से बहुत स्पष्ट होना चाहिए। अगर आपको किसी स्पष्टीकरण की ज़रूरत है, तो संकोच मत करो!

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