2012-01-03 15 views
28

मैं दो सजावटकर्ताओं द्वारा एक Django दृश्य को सजाने की कोशिश कर रहा हूं, एक लॉगिन की जांच के लिए, और एक जांच_एक्टिव के लिए है।Django में एक दृश्य के लिए एकाधिक सजावटी: निष्पादन आदेश

पहले एक में निर्मित @login_required है, और दूसरा एक निम्नलिखित है:

def active_required(function): 
    dec = user_passes_test(lambda u: u.is_active, '/notallowed', '') 
    return dec(function) 

अब, अंदर बाहर अजगर काम में सज्जाकार, तथापि निम्नलिखित काम नहीं करता:

@active_required 
@login_required 
def foo(request): 
    ... 

मैं पहले यह जांचना चाहता हूं कि उपयोगकर्ता लॉग इन है या नहीं, और यदि लॉगिन नहीं किया गया है तो लॉगिन पेज पर रीडायरेक्ट करना है, और यदि वह लॉग इन है, तो मैं यह जांचना चाहता हूं कि वह सक्रिय है या नहीं, और यदि नहीं, तो रीडायरेक्ट करें '/notallowed'

क्या होता है कि अगर login_required विफल रहता है, उपयोगकर्ता लॉगिन पृष्ठ पर पुनः निर्देशित नहीं है, लेकिन @active_required निष्पादित किया जाता है, और के बाद से उपयोगकर्ता उस मामले में शून्य है, @active_required डेकोरेटर विफल रहता है और उपयोगकर्ता /notallowed पर भेज दिया जाएगा।

क्रम बदलने से काम करने लगता है

,

@login_required 
@active_required 
def foo(request): 
    ... 

लेकिन मुझे लगता है कि वहाँ कुछ इस दृष्टिकोण भी गलत है।

दो सजावट को गठबंधन करने का सही तरीका क्या है, और निष्पादन आदेश सरल पायथन सजावट से अलग क्यों होता है?

उत्तर

29

अब, पायथन में सज्जाकार अंदर बाहर

खैर मैं लगता है कि अंदर बाहर की अपनी परिभाषा पर निर्भर करता है काम करते हैं। आपके मामले में आप login_required पहले निष्पादित करने के लिए, और इसलिए इसे "सबसे बाहरी" (ऊपर) डेकोरेटर

होना चाहिए आप का उल्लेख किया, अपने पिछले उदाहरण से काम करता है, और वास्तव में इस

करने के लिए सही तरीका है के रूप में चाहते हैं संपादित

शायद भ्रम की स्थिति के साथ है कैसे (इन विशेष) सज्जाकार काम

login_required(original_view) कोई नया दृश्य है, जो पहली जांच करता है कि आप लॉग इन हैं देता है, और उसके बाद कॉल

original_view

तो

login_required(
    active_required(
     my_view 
    ) 
) 

first checks if you are logged in, then 
    first(second) checks if you are active, then 
     runs my_vew 
+2

हम्म, मैं अभी भी थोड़ा आदेश के बारे में उलझन में हूँ: http://stackoverflow.com/a/739665/72436 और http://stackoverflow.com/a/8715839/72436 अन्यथा सुझाव देते हैं। – ustun

+1

ठीक है, मुझे लगता है कि आपने इसे दबाया है, अंतर एक फंक्शन बनाम इसे वापस करने में निहित है। – ustun

10

अगर सजावटी लोगों को वास्तव में अद्वितीय कार्यक्षमता है तो यह वास्तव में समझ में आता है। आपके विवरण के आधार पर, ऐसा कोई परिदृश्य नहीं होगा जहां आप active_required का उपयोग करना चाहेंगे लेकिन login_required नहीं। इसलिए, यह login_and_active_required सजावट करने वाला अधिक समझ में आता है जो तदनुसार दोनों शाखाओं की जांच करता है। टाइप करने के लिए कम, दस्तावेज़ के लिए कम, और समस्या को अस्वीकार करता है।

+0

ठीक है, मैं चाहिए Django builtins कस्टम कोड तुलना में अधिक विश्वसनीय हो गया होता। यह थोड़ा अजीब बात है कि Django में यह सजावट नहीं है, हालांकि, यह बहुत आम होना चाहिए। मैंने कुछ बग रिपोर्ट देखी हैं जिन्हें WONTFIX के रूप में चिह्नित किया गया था। – ustun

+0

सहमत हुए। चूंकि 'is_active' अंतर्निहित है, और अधिकांश परिदृश्यों में' login_required' को बहुत अधिक अस्वीकार करता है, देवताओं को इस आउट ऑफ़ द बॉक्स के लिए जिम्मेदार होना चाहिए था, लेकिन सीएएस ला विस। –

13

डेकोरेटर क्रम में वे स्रोत में प्रदर्शित में लागू होते हैं।इस प्रकार, अपने दूसरे उदाहरण:

def foo(request): 
    ... 
foo = login_required(active_required(foo)) 

इस प्रकार, यदि एक डेकोरेटर के कोड कुछ द्वारा निर्धारित (या द्वारा सुनिश्चित) दूसरे पर निर्भर करता है, तो आप डाल करने के लिए है:

@login_required 
@active_required 
def foo(request): 
    ... 

निम्नलिखित के बराबर है निर्भर सजावटी "अंदर" डिप्लेन्ड-ऑन सजावटकर्ता।

लेकिन, जैसा कि क्रिस प्रैट नोट, आप डेकोरेटर निर्भरता होने से बचना चाहिए; जब आवश्यक हो, तो एक नया सजावट तैयार करें जो सही क्रम में दोनों को कॉल करता है।

+0

ठीक है, लेकिन मुझे सिर्फ विपरीत चाहिए: सबसे पहले, login_required लागू किया जाना चाहिए, फिर active_required। तो, क्या यह मेरे द्वारा दिए गए पहले उदाहरण में नहीं होना चाहिए? – ustun

+0

इस मामले में, 'login_required' पहले लागू किया गया है - इसके बारे में सोचने का एक तरीका यह है कि 'foo' को कॉल' login_required' द्वारा लौटाए गए फ़ंक्शन के माध्यम से गुजरता है, फिर 'active_required' द्वारा वापस किए गए फ़ंक्शन के माध्यम से। आप पीडीबी के साथ इसके माध्यम से कदम उठा सकते हैं, या मेरा मतलब यह देखने के लिए डीबगिंग 'प्रिंट' जोड़ सकते हैं। – dcrosta

4

इसे थोड़ा और समझाने के लिए (मुझे पहले भी उलझन में था): active_required पहले इस अर्थ में लागू किया गया है कि यह my_view लेता है और इसे कुछ कोड में लपेटता है। फिर login_required लागू किया गया है और कुछ और कोड में परिणाम लपेटता है।

लेकिन जब my_view के इस लिपटे संस्करण वास्तव में शुरू हो जाती है, पहले कोड login_required से जोड़ा निष्पादित किया जाता है (यह जांच करना कि आप लॉग इन हैं), तो कोड active_required से जोड़ा निष्पादित किया जाता है (जाँच है कि आप सक्रिय कर रहे हैं) और फिर अंत में my_view निष्पादित किया गया है।

+0

यहां टिप्पणियों में भ्रम को दूर करने के लिए अंतर करने का यह एक अच्छा तरीका है: http://stackoverflow.com/a/8715821/781695 – Medorator

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