第一種:直接在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指定。
- 第三種和第二種的區別就在於:前者深入到分發過程中,在分發前做了驗證;后者在分發后做的驗證。
