2012-03-12 14 views
7

मैं कुछ मौजूदा कोड को बेहतर बनाने की कोशिश कर रहा हूं जो मूल रूप से एक बड़ा डेटा तैयार करने के लिए 3 मिनट लगते हैं (फिर अजाक्स द्वारा लौटाया जाता है)। पुराना कोड एक बड़ी क्वेरीसेट पर पुनरावृत्त होता है, विभिन्न प्रकार की संबंधित वस्तुओं से जानकारी इकट्ठा करता है। जो मैंने पढ़ा है, और एसक्यूएल लॉग की निगरानी से, क्वेरीसेट पर पुनरावृत्ति आमतौर पर एक बुरा विचार है, क्योंकि प्रत्येक आइटम के लिए एसक्यूएल निष्पादित किया जाता है। इसके बजाय, मैं एक एकल SQL कथन में जानकारी एकत्र करने के लिए मानों का उपयोग कर रहा हूं, फिर उसके माध्यम से पुनरावृत्ति कर रहा हूं। इस तकनीक का उपयोग करके, मैंने निष्पादन समय को 15 सेकंड से कम कर दिया है (और मैं अभी भी नहीं कर रहा हूं)। हालांकि, क्योंकि अब मैं मॉडल ऑब्जेक्ट्स का उपयोग नहीं कर रहा हूं, मैं get_FOO_display() का उपयोग नहीं कर सकता। क्या मान() का उपयोग करते समय इस कार्यक्षमता का उपयोग करने का कोई तरीका है?Django: मानों का उपयोग() और get_FOO_display()?

सरलीकृत, मूल था:

for user in users: 
    data.append(user.get_name_display()) # Appends 'Joe Smith' 
return data 

और नया कोड है:

for user in users.values('name'): 
    data.append(user['name']) # Appends 'JSmith001', which is incorrect 
return data 

इसके अलावा, वहाँ मॉडल के निर्माण को बचाने के लिये किसी अन्य तरह से अभी तक वस्तुओं है कि अगर केवल एक ही एसक्यूएल की आवश्यकता है बैकएंड पर बयान, मुझे इसके बारे में जानना अच्छा लगेगा। धन्यवाद!

+0

अधिक कोड को देखने के लिए की आवश्यकता है। जवाब देने के लिए यह बहुत सामान्य है। –

+0

क्षमा करें, मैंने उपरोक्त टिप्पणियां जोड़ दी हैं, लेकिन मुझे यकीन नहीं है कि आप और क्या देखना चाहते हैं। – Nathan

उत्तर

5

सामान्यतः, यह संभवतः एक प्रबंधक-आधारित क्वेरी का उपयोग करने के लिए बेहतर और आसान होगा जो मॉडल ऑब्जेक्ट्स देता है। ऐसा लगता है कि आपके मूल दृष्टिकोण के साथ इस मुद्दे की तरह यह नहीं है कि आप अपनी क्वेरीसेट पर पुनरावृत्त कर रहे थे (जैसा कि @ahmoo कहता है, यह एक प्रदर्शन मुद्दा नहीं है), लेकिन आपके पुनरावृत्ति लूप के भीतर आपको अतिरिक्त संबंधित वस्तुएं मिल रही थीं, जिसके लिए एक या अधिक की आवश्यकता थी प्रत्येक रिकॉर्ड के लिए अतिरिक्त प्रश्न।

  • यह सबसे अधिक प्रासंगिक की तरह लगता है select_related(), जो प्रभावी रूप से एक मेज प्रारंभिक क्वेरी के लिए डेटा शामिल करने के लिए पर शामिल होने के क्या करेंगे है:

    प्रश्नों है कि अभी भी मॉडल उदाहरणों वापसी के साथ प्रदर्शन में सुधार करने के कई तरीके हैं विदेशी कुंजी से संबंधित सभी वस्तुओं।

  • यदि यह अपर्याप्त है, तो आप extra() के साथ अपने मॉडल उदाहरणों में भी डेटा जोड़ सकते हैं, जो आपको अपने एसक्यूएल में सबक्विरीज़ चिपकाने की अनुमति देता है।

  • और यदि यह असफल हो जाता है, तो आप प्रबंधक उदाहरण पर .raw() विधि का उपयोग करके raw SQL queries निष्पादित कर सकते हैं, जो अभी भी मॉडल के उदाहरणों को वापस कर देगा।

मूल रूप से, अगर आप एक तरीका है कि आप उदाहरण के प्रति एक पंक्ति देता में एसक्यूएल में कर सकते हैं, वहाँ Django में कर और मॉडल उदाहरणों वापस पाने के लिए एक तरीका है।

, अपने मूल प्रश्न का उत्तर देने हालांकि, आप फील्ड वर्ग के माध्यम से प्रदर्शन नाम प्राप्त कर सकते हैं - यह सिर्फ बदसूरत है:

def get_field_display(klass, field, value): 
    f = klass._meta.get_field(field) 
    return dict(f.flatchoices).get(value, value) 

# usage 
get_field_display(User, 'name', 'JSmith001') 
+0

एचएम। जब मैं 'user.objects.all()' करता हूं तो उस तरह से 'प्रिंट user.name'' जैसा कुछ करता है, यह केवल एक SQL कथन निष्पादित करता है। हालांकि, जब मैं 'user.team.name' प्रिंट करता हूं, तो अब यह प्रत्येक उपयोगकर्ता के लिए एक SQL कथन निष्पादित करता है, भले ही मैं select_related का उपयोग करता हूं या नहीं। – Nathan

+0

'user.team' एक विदेशी कुंजी संबंध है, या कई से अधिक रिश्ते? 'select_related()' केवल 'विदेशीके' फ़ील्ड का पालन करता है, मुझे लगता है। – nrabinowitz

+0

क्षमा करें, यह कई से अधिक रिश्ते हैं। ठीक है, मैंने इसे पढ़ लिया था, और यह समझने से पहले कि यह वर्तमान में केवल एक विकास था, prefetch_related संक्षेप में कोशिश की। मुझे लगता है कि यही कारण है कि मैं अपने डेटा को डिक्ट्स में प्रीपॉलेट करने के लिए मूल्यों के साथ जा रहा हूं, जो कि महान काम कर रहा है (अंतिम फिक्स के साथ 2.7 सेकेंड तक) सिवाय इसके कि मैं get_FOO_display का उपयोग नहीं कर सकता। – Nathan

3

क्वेरीसमूहों से अधिक पुनरावृत्ति आम तौर पर एक बुरा विचार है, क्योंकि एसक्यूएल प्रत्येक आइटम

सच नहीं है कि के लिए मार डाला जाता है। नीचे the official docs से लिया जाता है:

एक क्वेरीसमूह iterable है, और यह अपने डेटाबेस क्वेरी पहली बार जब आप पुनरावृति कार्यान्वित पर

मुझे लगता है कि समस्या से users की परिभाषा के साथ क्या करना है तुम्हारा कोड। आपने इसे क्या सौंपा?

+0

हम भी बहुत सी विदेशी कुंजी का पालन करते हैं, जिसका अर्थ है कि हम 'user.team.name' दबाते हैं। आप सही हैं कि वे केवल साधारण वस्तुओं पर एक ही क्वेरी निष्पादित करते हैं, लेकिन जब मैं इसे अब डीबग करने का प्रयास करता हूं, जैसे ही मैं एक विदेशी कुंजी का पालन करता हूं, प्रत्येक उपयोगकर्ता के लिए लॉग में एक अलग SQL कथन होता है। – Nathan

+0

@Nathan - क्या आप 'user.team.name' या' user.name' तक पहुंचने का प्रयास कर रहे हैं? आपकी मूल पोस्ट में, ऐसा लगता है कि आपको 'user.name' की आवश्यकता है लेकिन फिर आपने' user.team.name' के बारे में उल्लेख किया है। यह शायद सबसे अच्छा है यदि आप 'टीम' मॉडल की परिभाषा पोस्ट कर सकते हैं और जो भी आप प्राप्त करना चाहते हैं उस पर विस्तार कर सकते हैं। – tamakisquare

+0

दोनों, साथ ही अलग-अलग रिश्तों से अलग-अलग चीजों की मेजबानी, जो कई से अधिक और विदेशी कुंजी का संयोजन है। मुझे लगता है कि अब दो प्राथमिक प्रश्न हैं, 1) क्या मॉडल मॉडल के उदाहरण के बिना मॉडल के लिए डिस्प्ले नाम प्राप्त करना संभव है, और 2) एकाधिक SQL कॉल के बिना मैं क्वेरीसेट के माध्यम से बेहतर कैसे हो सकता हूं। मैं सोच रहा हूं कि # 1 का जवाब 'नहीं' है, और # 2 का जवाब या तो एक पूरी तरह से अलग एसओ पोस्ट है, या अधिक कोड आत्मनिरीक्षण है। – Nathan

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