2013-10-29 2 views
13

मैं सोच रहा था कि क्या Django में एक संबंधित क्षेत्र है, विशेष रूप से एक से कई रिश्तों के "कई" हिस्से को बताते हुए, prefetch_related() के माध्यम से वास्तव में इसे प्राप्त किए बिना, क्या बताया गया है?Django: क्या आप बता सकते हैं कि कोई संबंधित फ़ील्ड इसे लाए बिना प्रीफ़ेट किया गया है?

class Question(Model): 
    """Class that represents a question.""" 

class Answer(Model): 
    """Class the represents an answer to a question.""" 
    question = ForeignKey('Question', related_name='answers') 

आम तौर पर, एक सवाल, सबसे कारगर तरीका यह प्राप्त करने के लिए निम्न कार्य करना होगा के लिए उत्तर की संख्या प्राप्त करने (:

तो, एक उदाहरण के रूप, मान लीजिए कि मैं इन मॉडलों डालते हैं क्योंकि Django डॉक्स राज्य है कि count() अगर आप सिर्फ एक गिनती) की जरूरत है और अधिक कुशल है: इस तरह के पहले के माध्यम से दोहराया होने के रूप में

# Note: "question" is an instance of class Question. 
answer_count = question.answers.count() 
हालांकि कुछ मामलों जवाब एक prefetch_related() कॉल (या किसी तरह के माध्यम से दिलवाया गया हो सकता है में

, उत्तर रों)। ताकि इस तरह की स्थितियों में, यह अधिक यह करने के लिए कुशल होगा (क्योंकि हम अतिरिक्त गिनती क्वेरी को छोड़ चाहते हैं):

if question.answers_have_been_prefetched: # Does this exist? 
    answer_count = len(question.answers.all()) 
else: 
    answer_count = question.answers.count() 
:

# Answers were fetched via prefetch_related() 
answer_count = len(question.answers.all()) 

तो क्या मैं वास्तव में क्या करना चाहते हैं की तरह कुछ है

यदि यह मायने रखता है तो मैं Django 1.4 का उपयोग कर रहा हूं। अग्रिम में धन्यवाद।

संपादित करें: जोड़ा गया स्पष्टीकरण कि prefetch_related() उत्तर देने का एकमात्र तरीका नहीं है।

+0

यहाँ एक आवरण लाइब्रेरी का उपयोग कर के पूरे मुद्दे ताकि आप डॉन है ' टी, वास्तव में, इस तरह की चीजों के बारे में चिंता करने की ज़रूरत है। जब तक आप इसे वास्तविक बाधा बनने के लिए माप नहीं लेते हैं, तो केवल सरल विधि का उपयोग करें और अनियंत्रित जटिलता न जोड़ें। हालांकि, Django स्रोत कोड में थोड़ा पोकिंग करने के बाद, मुझे कुछ संकेत मिले हैं। यदि आप अभी भी इस हैक को आजमाने का आग्रह करते हैं, तो आप 'obj._prefetched_objects_cache' आज़मा सकते हैं, या वैकल्पिक रूप से, आप बस 'प्रिंट dir (question.answers)' का प्रयास कर सकते हैं और देख सकते हैं कि क्या आप वहां कोई कैश-संबंधित दिखने वाले पैरामीटर देखते हैं या नहीं। – kazagistar

+0

यह एक विशाल बाधा नहीं है, नहीं। मैं वास्तव में ऐप से बाहर नरक को अनुकूलित करने की कोशिश कर रहा था और प्रश्नों की संख्या को कम से कम भालू में लाया था। सहमत हैं कि अगर एकमात्र तरीका हैकी है, तो यह इसके लायक नहीं है। मुझे स्पष्टीकरण देना चाहिए: prefetch_related सिर्फ एक उदाहरण था। नतीजों को किसी अन्य तरीके से भी लाया जा सकता था (उदाहरण के लिए कोड में पहले सवाल पूछना)। यही कारण है कि मैं कुछ सामान्य समाधान की उम्मीद कर रहा था। – Chad

+2

यह वास्तव में अच्छा होगा अगर Django आपको पूर्वनिर्धारित संबंधों के स्वचालित इन-मेमोरी फ़िल्टरिंग का विकल्प चुनने दे, ताकि आप अपने डीएसएल का उपयोग करके पहले से मौजूद डेटा की जांच करने के लिए बस एक नई क्वेरी नहीं बना सकें। – skatenerd

उत्तर

20

हां, Django माता-पिता मॉडल उदाहरण के _prefetched_objects_cache विशेषता में प्रीफेच किए गए परिणाम संग्रहीत करता है।

तो तुम कुछ कर सकते हैं की तरह:

instance = Parent.objects.prefetch_related('children').all()[0] 

try: 
    instance._prefetched_objects_cache[instance.children.prefetch_cache_name] 
    # Ok, it's pefetched 
    child_count = len(instance.children.all()) 
except (AttributeError, KeyError): 
    # Not prefetched 
    child_count = instance.children.count() 

Django स्रोत ट्रंक में relevant use या the equivalent v1.4.9 में देखें

+0

इसके लिए धन्यवाद, लेकिन मुझे स्पष्ट करना चाहिए: prefetch_related सिर्फ एक उदाहरण था। नतीजों को किसी अन्य तरीके से भी लाया जा सकता था (उदाहरण के लिए कोड में पहले सवाल पूछना)। – Chad

+2

संबंधित प्रबंधक एक्सेस आमतौर पर कैश नहीं होते हैं, आपको शायद अपने स्वयं के ज्ञापन रैपर को लागू करना होगा: https://docs.djangoproject.com/en/dev/topics/db/optimization/#understand-queryset-evaluation –

+0

आह, ठीक है, यह जानना अच्छा है। इसलिए जब आप prefetch_related का उपयोग करते हैं तो वे केवल कैश हो जाते हैं। स्पष्टीकरण के लिए धन्यवाद। इस हैक की तरह लगता है प्रयास के लायक नहीं है और मुझे सिर्फ गिनती करना चाहिए(), लेकिन आपने मुझे वह जानकारी दी जो मुझे चाहिए। – Chad

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

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