2009-03-29 7 views
5

मान लें कि मेरे पास एक ऐसी प्रणाली है जिसमें कुछ पेज हैं जो सार्वजनिक हैं (दोनों गैर-प्रमाणीकृत उपयोगकर्ता और लॉग-इन उपयोगकर्ता देख सकते हैं) और अन्य जो केवल लॉग-इन उपयोगकर्ता देख सकते हैं।क्या एक django टेम्पलेट जानता है कि जिस दृश्य से इसे देखा गया है, उसमें @login_required सजावट है?

मैं चाहता हूं कि टेम्पलेट पृष्ठों के इन दो वर्गों में से प्रत्येक के लिए थोड़ा अलग सामग्री दिखाए। @login_required व्यू सजावट हमेशा उन विचारों पर उपयोग किया जाता है जो केवल लॉग-इन उपयोगकर्ता देख सकते हैं। हालांकि, मेरे टेम्पलेट को यह जानने की आवश्यकता होगी कि इस सजावट का उपयोग उस दृश्य पर किया जाता है जहां से टेम्पलेट का आह्वान किया गया था।

कृपया ध्यान रखें कि मुझे कोई परवाह नहीं है कि उपयोगकर्ता सार्वजनिक पृष्ठों के लिए लॉग इन है या नहीं। मुझे इस बात की परवाह है कि क्या एक पृष्ठ आम जनता द्वारा देखा जा सकता है, और @login_required सजावट की अनुपस्थिति मुझे बताएगी।

क्या कोई मुझे इस बात पर संकेत दे सकता है कि टेम्पलेट कैसे पता चलेगा कि टेम्पलेट से किस प्रकार से एक विशेष सजावटी का उपयोग किया जा रहा है?

उत्तर

5

हां, यह संभव है, लेकिन बहुत सी सरल नहीं है। जटिल कारक यह है कि Django के login_required सजावटी वास्तव में django.contrib.auth.decorators._CheckLogin पर समाप्त होने के लिए, संकेतों के एक स्तर (एक गतिशील फ़ंक्शन और एक अन्य सजावट) के माध्यम से गुजरता है, जो __call__ विधि वाला वर्ग है।

मान लीजिए कि आप एक गैर Django, उपवन के प्रकार सजाया समारोह है कि इस तरह दिखता है करते हैं:

def my_decorator(func): 
    def inner(): 
     return func() 
    return inner 

@my_decorator 
def foo(): 
    print foo.func_name 

# results in: inner 

देखने के लिए समारोह foo लिपटे कर दिया गया है समारोह वस्तु का नाम की जाँच के रूप में सरल किया जा सकता है अगर जाँच हो रही है । आप इसे फ़ंक्शन के अंदर कर सकते हैं। नाम वास्तव में अंतिम रैपर फ़ंक्शन का नाम होगा। अधिक जटिल मामलों के लिए, यदि आप विशेष रूप से कुछ ढूंढ रहे हैं तो आप मौजूदा फ्रेम से बाहरी फ्रेम को चलाने के लिए inspect मॉड्यूल का उपयोग कर सकते हैं।

हालांकि, Django के मामले में, सजावट वास्तव में _CheckLogin कक्षा का एक उदाहरण है जिसका अर्थ है कि फ़ंक्शन वास्तव में एक फ़ंक्शन नहीं है, और इसलिए func_name संपत्ति नहीं है: उपरोक्त कोड को आजमाने का प्रयास अपवाद उठाएगा ।

django.contrib.auth.decorators._CheckLogin के लिए स्रोत कोड को देखते हुए, यह दिखाता है कि _CheckLogin उदाहरण में login_url संपत्ति होगी।इस के लिए परीक्षण करने के लिए एक बिल्कुल स्पष्ट बात है:

@login_required 
def my_view(request): 
    is_private = hasattr(my_view, 'login_url') 

क्योंकि _CheckLogin भी अन्य प्रमाणन सज्जाकार लागू करने के लिए प्रयोग किया जाता है, इस दृष्टिकोण भी permission_required के लिए काम करेंगे, आदि मैं वास्तव में कभी इस का उपयोग करने की आवश्यकता मिला है हालांकि, मैं वास्तव में इस बात पर टिप्पणी नहीं कर सकता कि आपको क्या देखना चाहिए यदि आपके पास एक ही दृश्य के आसपास कई सजावटी हैं ... पाठक को एक अभ्यास छोड़ दिया गया, मुझे लगता है (फ्रेम ढेर का निरीक्षण करें?)।

अपरिचित संपादकीय सलाह के रूप में, हालांकि, मैं यह कहने के लिए फ़ंक्शन की जांच करूँगा कि यह इस तरह लपेटा गया है कि मुझे थोड़ा सा झटका लगता है। आप संभवत: कल्पना कर सकते हैं कि किसी अन्य डेवलपर को किसी अन्य डेवलपर पर थप्पड़ के रूप में प्रोजेक्ट में आने पर अप्रत्याशित व्यवहार होने का इंतजार है। वास्तव में, आप django ढांचे में परिवर्तनों के संपर्क में भी आ गए हैं ... एक सुरक्षा जोखिम होने का इंतजार कर रहा है।

मैं उस कारण के लिए वान गैले के दृष्टिकोण की सिफारिश करता हूं जो स्पष्ट है, और इसलिए एक और अधिक मजबूत कार्यान्वयन।

+0

आपका पहला कोड ब्लॉक लिखित के रूप में काम नहीं करेगा। my_decorator इसे पारित समारोह को खत्म कर देता है, इसलिए foo में एक प्रिंट स्टेटमेंट डालना बेकार है। –

+0

धन्यवाद डेविड, आप सही हैं ... मैं मुख्य बिंदु पर जाने के लिए पहले ब्लॉक पर चमक रहा था, मैंने जो लिखा था उसे ध्यान से पढ़े बिना। संपादन की सराहना करें। –

+0

गहन उत्तर के लिए धन्यवाद। आपकी अंतिम टिप्पणी यह ​​है कि मैं क्या कर रहा था, भले ही मुझे लगता है कि कुछ और "पायथनिक" हो सकता है; मुझे दोहराने के बिना करने का तरीका। मुझे लगता है कि मेरे मामले में यह "सही" तरीका बहुत जटिल है और बहुत मजबूत नहीं है। –

3

मैं टेम्पलेट में एक अतिरिक्त संदर्भ चर पारित कर दूंगा।

तो, का मानना ​​है कि private: True और अन्य दृश्य की तरह एक चर से होकर गुजरेगा @login_required है private: False

+0

मैंने इसे अल्प अवधि में कर दिया। पूरी तरह से प्रभावी, लेकिन काफी पाइथनिक नहीं है क्योंकि मैं @login_required सजावट की अनुपस्थिति से यह मान प्राप्त कर सकता हूं। –

1

क्यों आपका टेम्प्लेट पता करने की जरूरत है पारित होगा? यदि @login_required सजावट का उपयोग किया जाता है, तो दृश्य स्वयं उन लोगों को रोकता है जो पृष्ठ तक पहुंचने से लॉग इन नहीं होते हैं और इसलिए टेम्पलेट को कभी भी शुरू नहीं करते हैं।

+0

शायद टेम्पलेट को कई स्थानों से संदर्भित किया गया है, कुछ प्रविष्टि बिंदु @login_required हैं, और कुछ नहीं। –

+0

हाँ, यही मैंने माना है। –

+0

ब्लेयरड सही है। टेम्पलेट मेरा base.html टेम्पलेट है जो मेरी वेबसाइट पर अन्य सभी टेम्पलेट्स का मूल अभिभावक है। –

0

टेम्पलेट्स पदानुक्रमित हैं तो @login_required संस्करण और "नहीं @login_required" संस्करण क्यों नहीं है, जिनमें से दोनों एक ही माता-पिता से प्राप्त होते हैं?

यह टेम्पलेट्स को बनाए रखने के लिए बहुत साफ और आसान रखेगा।

+0

एक सूक्ष्म अंतर है। मैं जो करना चाहता हूं उसके साथ। मैं अपने विचार में जांचना चाहता हूं कि कोई विशेष टेम्पलेट उपयोग किया गया है, विपरीत टेम्पलेट व्यवहार को लागू नहीं करता है। –

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