django:優雅裝飾類視圖的多種方法(以login_required舉例)


第一種:直接在url上下手。

    url(r'^comment/(?P<course_id>\d+)$', login_required(CommentsView.as_view()), name="comment")
  

補充說明
問題1:為什么可以這樣?
回答1:
1、回憶一下裝飾器的原理:將函數本身的引用作為參數傳遞給這個函數,由該函數定義一個同名函數,在此同名函數中進行別的操作后調用傳入函數,並返回這個同名函數的引用的過程被稱為:裝飾。具體參考:裝飾器詳解
2、所以?你把被調用的函數當作參數傳遞給這個裝飾器函數本身不就可以了?
第二種:使用method_decorator裝飾器

from django.contrib.auth.decorators import login_required
from django.utils.decorators import method_decorator


class LoginRequiredMixin(object):
    '''登錄狀態校驗'''
    @method_decorator(login_required(login_url='/login/'))
    def dispatch(self, request, *args, **kwargs):
        return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

補充說明

  • method_decorator裝飾器,是django自帶的一個裝飾器,其最主要的作用就是解決裝飾器不能直接的裝飾類視圖函數(method_decorator的作用是為函數視圖裝飾器補充第一個self參數)。
  • 它具有兩個參數,第一個參數是:裝飾器本身及它的參數;第二個參數是:給這個類中的哪個函數裝飾。
  • 如果你願意去看一下該裝飾器的源碼,我還是比較推薦的,所以我也為你准備了中文版:中文版:method_decorator裝飾器源碼解析
  • 關於dispatch()函數:在其View源碼中,它是起着請求映射分發的作用的,其實在執行as_view()的時候,內部就是在執行的就是self.dispatch()方法,你可以自己重寫一下,然后給重寫的加上裝飾器,就可以在其實施分發前進行了登錄驗證 了。
  • 使用說明:你需要讓你的類視圖函數繼承:LoginRequiredMixin,且在View之前。
  • 這種方法的使用還可以用於取消部分類視圖中的csrf驗證(僅列舉取消單個視圖處理類的csrf驗證,如果你需要將很多的處理類都取消csrf的話,可以使用繼承)。示例如下(也可以配合method_decorator的第二個參數,直接裝飾類):
from django.views import View
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt, csrf_protect


class TestView(View):
    """取消該視圖處理類中的csrf驗證"""
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(TestView, self).dispatch(self, request, *args, **kwargs)

    def get(self, request):
        pass

    def post(self, request):
        pass

第三種:利用繼承關系,實現在調用執行視圖函數前調用login__required()

from django.contrib.auth.decorators import login_required
class LoginRequiredMixin(object):
    '''登錄狀態校驗'''
    @classmethod
    def as_view(cls, **initkwargs):
        view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
        return login_required(view)
  • 在url最主要的還是要實現:login_required(CommentsView.as_view())
  • 而此時就是利用繼承優雅的實現。
  • 使用說明:你需要讓你的類視圖函數繼承:LoginRequiredMixin,且在View之前。

補充

  • login_required的跳轉函數:你可以不指定(會使用默認的),也可以在其參數中指定,也可以在settings.LOGIN_URL指定。
  • 第三種和第二種的區別就在於:前者深入到分發過程中,在分發前做了驗證;后者在分發后做的驗證。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM