2015-01-07 10 views
18

आम तौर पर, मैं कुछ प्रारंभिक चर सेट करने या उपयोगकर्ता की अनुमतियों के आधार पर कुछ तर्क जोड़ने के लिए कक्षा आधारित दृश्य की dispatch विधि का उपयोग करता हूं।Django: mixins और प्रेषण विधि के साथ एक वर्ग आधारित दृश्य

उदाहरण के लिए,

from django.views.generic import FormView 
from braces.views import LoginRequiredMixin 

class GenerateReportView(LoginRequiredMixin, FormView): 
    template_name = 'reporting/reporting_form.html' 
    form_class = ReportForm 

    def get_form(self, form_class): 
     form = form_class(**self.get_form_kwargs()) 
     if not self.request.user.is_superuser: 
      form.fields['report_type'].choices = [ 
       choice for choice in form.fields['report_type'].choices 
       if choice[0] != INVOICE_REPORT 
      ] 
     return form 

यह उम्मीद के रूप में काम करता है: एक अनाम उपयोगकर्ता एक पृष्ठों पर आता है, LoginRequiredMixin की dispatch विधि कहा जाता है, और फिर लॉगिन पृष्ठ पर रीडायरेक्ट।

लेकिन मैं कुछ अनुमतियों,

class GenerateReportView(LoginRequiredMixin, FormView): 

    def dispatch(self, *args, **kwargs): 
     if not (
      self.request.user.is_superuser or 
      self.request.user.is_manager 
     ): 
      raise Http404 
     return super(GenerateReportView, self).dispatch(*args, **kwargs) 
कुछ मामलों में यह काम नहीं करता है में

, इस दृश्य के लिए जोड़ सकते हैं या कुछ प्रारंभिक चर निर्धारित करते हैं, उदाहरण के लिए करना चाहते हैं क्योंकि mixins के dispatch तरीकों, का मानना ​​है कि विरासत, अभी तक नहीं बुलाया गया है। तो, उदाहरण के लिए, उपयोगकर्ता की अनुमति के लिए पूछने के लिए सक्षम होने के लिए, मैं LoginRequiredMixin से मान्यता दोहराना:

class GenerateReportView(LoginRequiredMixin, FormView): 

    def dispatch(self, *args, **kwargs): 
     if self.request.user.is_authenticated() and not (
      self.request.user.is_superuser or 
      self.request.user.is_manager 
     ): 
      raise Http404 
     return super(GenerateReportView, self).dispatch(*args, **kwargs) 

यह उदाहरण के लिए सरल है, लेकिन कभी कभी वहाँ एक मिश्रण में कुछ और अधिक जटिल तर्क हैं: इसके लिए जाँच करता है अनुमतियां, कुछ गणना करता है और इसे कक्षा विशेषता आदि में संग्रहीत करता है।

अभी के लिए मैं इसे मिश्रण से कुछ कोड कॉपी करके (ऊपर दिए गए उदाहरण की तरह) या dispatch दृश्य से कोड कॉपी करके इसे हल करता हूं किसी अन्य मिश्रण के लिए और उसे पहले क्रम में निष्पादित करने के बाद इसे विरासत में मिला (जो कि सुंदर नहीं है, क्योंकि यह नया मिश्रण केवल एक दृश्य द्वारा उपयोग किया जाता है)।

क्या इस तरह की समस्याओं को हल करने का कोई उचित तरीका है?

+0

पहले कॉल 'सुपर (जेनरेट रिपोर्टपोर्ट, स्वयं)। डिस्पैच (* args, ** kwargs) ''। तो प्रेषण के अंदर शेष नौकरी करें जो आप –

+2

@MihaiZamfir ओवरराइड कर रहे हैं यह काम नहीं करेगा क्योंकि, उदाहरण के लिए, 'LoginRequiredMixin''' 'HttpResponseRedirect'' ऑब्जेक्ट देता है, इसलिए यदि हम इसे एक चर में संग्रहीत करते हैं, तो यह जब तक हम '' प्रेषण' विधि के अंत में इस चर को वापस नहीं करते हैं, तब तक लॉगिन दृश्य पर रीडायरेक्ट नहीं करेंगे। – vero4ka

+0

लेकिन आप जांच सकते हैं कि प्रतिक्रिया एक रीडायरेक्ट है या नहीं, तो प्रेषण –

उत्तर

3

मैं कस्टम वर्ग है, जो सभी अनुमतियों

from django.views.generic import FormView 
from braces.views import AccessMixin 

class SuperOrManagerPermissionsMixin(AccessMixin): 
    def dispatch(self, request, *args, **kwargs): 
     if not request.user.is_authenticated(): 
      return self.handle_no_permission(request) 
     if self.user_has_permissions(request): 
      return super(SuperOrManagerPermissionsMixin, self).dispatch(
       request, *args, **kwargs) 
     raise Http404 #or return self.handle_no_permission 

    def user_has_permissions(self, request): 
     return self.request.user.is_superuser or self.request.user.is_manager 

# a bit simplyfied, but with the same redirect for anonymous and logged users 
# without permissions 


class SuperOrManagerPermissionsMixin(AccessMixin): 
    def dispatch(self, request, *args, **kwargs): 
     if self.user_has_permissions(request): 
      return super(SuperOrManagerPermissionsMixin, self).dispatch(
       request, *args, **kwargs) 
     else: 
      return self.handle_no_permission(request) 

    def user_has_permissions(self, request): 
     return request.user.is_authenticated() and (self.request.user.is_superuser 
                or self.request.user.is_manager) 


class GenerateReportView(SuperOrManagerPermissionsMixin, FormView): 
#Remove next two lines, don't need it 
    def dispatch(self, *args, **kwargs): 
     #or put some logic here 
     return super(GenerateReportView, self).dispatch(*args, **kwargs) 

और वर्ग GenerateReportView के कार्यान्वयन की जाँच लिखते थे (SuperOrManagerPermissionsMixin, FormView) को ओवरराइडिंग प्रेषण विधि

यदि आप मल्टीप का उपयोग करते हैं ली विरासत और माता-पिता वर्गों में से एक को कुछ सुधार की आवश्यकता है, इसे पहले सुधारना अच्छा है। यह कोड क्लीनर रखता है।

1

आपके द्वारा दिए गए उदाहरण के लिए, मैं django-braces से उपयोग करूंगा।

class GenerateReportView(UserPassesTestMixin, FormView): 
    def test_func(self, user): 
     return user.is_superuser or user.is_manager 

है कि आपके और अधिक जटिल तर्क लिए उपयुक्त नहीं है, तो एक अलग mixin बनाने में कोई ठीक दृष्टिकोण की तरह, के रूप में यह जटिल तर्क अच्छी तरह से समाहित लग रहा है।

संपादित
Django 1.9 के रूप में, UserPassesTestMixin अब Django में शामिल है: https://docs.djangoproject.com/en/1.11/topics/auth/default/#django.contrib.auth.mixins.UserPassesTestMixin

2

यह एक पुरानी पोस्ट है लेकिन अन्य लोग यहां आ सकते हैं, इसलिए मेरा प्रस्तावित समाधान यहां है।

जब आप कहते हैं कि

"[...] मैं, इस दृश्य या सेट कुछ प्रारंभिक चर के लिए कुछ अनुमतियां जोड़ने के लिए उदाहरण [...] आपके विचार के प्रेषण विधि में उन लोगों के प्रारंभिक चर स्थापित करने की "

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

def set_initial_variables(): 
    self.hey = something 
    return 

def get(blablabla): 
    self.set_initial_variables() 
    return super(blabla, self).get(blabla) 

यह शायद कॉपीी से क्लीनर है अपने दृश्य के प्रेषण में अपने मिश्रण के कोड को एनजी और पेस्ट करना।

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