15

में मैंने एक कक्षा बनाई है जो ListView और दो कस्टम मिश्रणों को उप-वर्गीकृत करता है जिन्होंने get_context_data फ़ंक्शन लागू किया है। जब मैं निष्पादित MyListView यह केवल "ListSortedMixin" प्रिंटपायथन एकाधिक विरासत फ़ंक्शन ओवरराइडिंग और सूची दृश्य django

from django.views.generic import ListView 

class ListSortedMixin(object): 
    def get_context_data(self, **kwargs): 
     print 'ListSortedMixin' 
     return kwargs 

class ListPaginatedMixin(object): 
    def get_context_data(self, **kwargs): 
     print 'ListPaginatedMixin' 
     return kwargs 

class MyListView(ListSortedMixin, ListPaginatedMixin, ListView): 
    def get_context_data(self, **context): 
    super(ListSortedMixin,self).get_context_data(**context) 
    super(ListPaginatedMixin,self).get_context_data(**context) 
    return context 

: मैं बच्चे वर्ग पर इस समारोह को ओवरराइड करना चाहता था। किसी कारण से पाइथन MyListView.get_context_data के स्थान पर ListSortedMixin.get_context_data निष्पादित कर रहा है। क्यूं कर?

यदि मैं विरासत आदेश ListPaginatedMixin, ListSortedMixin, ListView पर बदलता हूं, ListPaginatedMixin.get_context_data निष्पादित किया जाता है।

मैं get_context_data फ़ंक्शन को ओवरराइड कैसे कर सकता हूं?

उत्तर

16

यह एक पुराना सवाल है, लेकिन मुझे विश्वास है कि उत्तर गलत है। आपके कोड में एक गलती है।यह पढ़ना चाहिए:

class MyListView(ListSortedMixin, ListPaginatedMixin, ListView): 
    def get_context_data(self, **context): 
     super(MyListView,self).get_context_data(**context) 
     return context 

जिस क्रम में get_context_data बुलाया जाएगा MyListView की घोषणा के रूप में विनिर्दिष्ट उसी क्रम इस प्रकार है। सुपर की तर्क MyListView है और सुपर क्लास नहीं है।

अद्यतन:

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

from django.views.generic import ListView 

class ListSortedMixin(object): 
    def get_context_data(self, **kwargs): 
     print 'ListSortedMixin' 
     return super(ListSortedMixin,self).get_context_data(**context) 

class ListPaginatedMixin(object): 
    def get_context_data(self, **kwargs): 
     print 'ListPaginatedMixin' 
     return super(ListPaginatedMixin,self).get_context_data(**context) 

class MyListView(ListSortedMixin, ListPaginatedMixin, ListView): 
    def get_context_data(self, **context): 
     return super(MyListView,self).get_context_data(**context) 

MyListView लिए एमआरओ तो है:।

  1. MyListView
  2. ListSortedMixin
  3. ListPaginatedMixin
  4. ListView
  5. जो भी ListViewसे ऊपर है... एन। ऑब्जेक्ट

उन्हें एक-एक करके कॉल करना काम कर सकता है, लेकिन ऐसा नहीं है कि इसका उपयोग कैसे किया जाए।

अद्यतन 2

कॉपी और पेस्ट उदाहरण मेरी बात साबित करने के लिए।

class Parent(object): 
    def get_context_data(self, **kwargs): 
     print 'Parent' 

class ListSortedMixin(object): 
    def get_context_data(self, **kwargs): 
     print 'ListSortedMixin' 
     return super(ListSortedMixin,self).get_context_data(**kwargs) 

class ListPaginatedMixin(object): 
    def get_context_data(self, **kwargs): 
     print 'ListPaginatedMixin' 
     return super(ListPaginatedMixin,self).get_context_data(**kwargs) 

class MyListView(ListSortedMixin, ListPaginatedMixin, Parent): 
    def get_context_data(self, **kwargs): 
     return super(MyListView,self).get_context_data(**kwargs) 


m = MyListView() 
m.get_context_data(l='l') 
+0

इस मामले में 'सुपर (MyListView, self) .get_context_data (** संदर्भ)' 'ListSortedMixin.get_context_data (स्वयं, ** संदर्भ) 'जैसा ही है। मुझे लगता है कि [पिछले जवाब] (http://stackoverflow.com/a/9939867/959819) सही है: मुझे माता-पिता को एक-एक करके काम करने की ज़रूरत है। –

+0

समस्या यह है कि आपके मिश्रित सुपर कॉल नहीं करते हैं। भले ही मिश्रित 'ऑब्जेक्ट' से उत्तराधिकारी हों, उन्हें सुपर कॉल करना चाहिए। एमआरओ (विधि संकल्प आदेश) में अगली वस्तु के लिए सुपर प्रतिनिधि, जो उस आदेश पर निर्भर करता है जिसमें वे MyListView की घोषणा में निर्दिष्ट किए गए थे। मैं इसे और अधिक स्पष्ट करने के लिए उपरोक्त मेरा उत्तर अपडेट करूंगा। –

+0

बिल्कुल। इसलिए आपके उदाहरण में बुलाया गया विधि केवल 'ListSortedMixin' है। मुझे मैन्युअल रूप से सभी माता-पिता कार्यों को कॉल करने की आवश्यकता है। –

10

यदि आप जो करने का प्रयास कर रहे हैं वह निश्चित क्रम में अधिलेखित विधियों को कॉल करना है। इस वाक्यविन्यास का प्रयोग करें:

class MyListView(ListSortedMixin, ListPaginatedMixin, ListView): 
    def get_context_data(self, **context): 
    ListSortedMixin.get_context_data(self, **context) 
    ListPaginatedMixin.get_context_data(self, **context) 
    return context 

सुपर इस मामले में काम नहीं करेगा। super(type[, object]) के लिए मैन्युअल देखें:

वापसी एक प्रॉक्सी उद्देश्य यह है कि प्रतिनिधियों विधि माता-पिता या प्रकार की भाई वर्ग के लिए कहता है। यह विरासत में प्राप्त विधियों तक पहुंचने के लिए उपयोगी है जो कक्षा में ओवरराइड किए गए हैं। खोज आदेश वही है जो getattr() द्वारा उपयोग किया जाता है सिवाय इसके कि प्रकार स्वयं छोड़ दिया जाता है।

सुपर के लिए दो सामान्य उपयोग के मामले हैं। एकल विरासत के साथ एक वर्ग पदानुक्रम में, सुपर क्लाइंट को को स्पष्ट रूप से नाम दिए बिना संदर्भित किया जा सकता है, इस प्रकार कोड को बनाए रखने योग्य बना दिया जा सकता है। यह अन्य प्रोग्रामिंग भाषाओं में सुपर के उपयोग को बारीकी से समानांतर उपयोग करता है।

दूसरा उपयोग केस में गतिशील निष्पादन वातावरण में सहकारी एकाधिक विरासत का समर्थन करना है। यह उपयोग केस पायथन के लिए अद्वितीय है और स्थैतिक रूप से संकलित भाषाओं या भाषाओं में नहीं मिला है जो केवल समर्थन एकल विरासत है। इससे "डायमंड आरेख" लागू करना संभव हो जाता है जहां एकाधिक आधार वर्ग समान विधि लागू करते हैं। अच्छा डिज़ाइन यह निर्देश देता है कि इस विधि में प्रत्येक मामले में हस्ताक्षर एक ही कॉलिंग है (क्योंकि कॉल का क्रम रनटाइम पर निर्धारित होता है, क्योंकि वह ऑर्डर कक्षा पदानुक्रम, में परिवर्तनों को अपनाना है और क्योंकि उस क्रम में भाई कक्षाएं शामिल हैं जो अज्ञात हैं रनटाइम से पहले )।

तो सुपर का तर्क वह वर्ग है जिसका माता-पिता या भाई वर्ग प्रॉक्सी आप प्राप्त करना चाहते हैं। super(ListSortedMixin,self).get_context_data(**context)ListSortedMixin के get_context_data पर कॉल नहीं करेगा। यह विधि संकल्प आदेश (एमआरओ) पर निर्भर करता है, जिसे आप print MyListView.__mro__

तो super() माता-पिता या भाई के get_context_data पर कॉल करेंगे। निष्पादन का क्रम वर्ग पदानुक्रम में परिवर्तनों को स्वीकार करता है, और क्योंकि उस क्रम में स्कीलिंग कक्षाएं शामिल हो सकती हैं जो रनटाइम से पहले अज्ञात हैं।

+0

तेज प्रतिक्रिया के लिए धन्यवाद! अच्छा स्पष्टीकरण, मैं इसे अब समझता हूं :) –

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