LoginRequiredMixin類介紹

根據官網https://docs.djangoproject.com/en/1.11/topics/auth/default/中的介紹

from django.contrib.auth.mixins import LoginRequiredMixin

class MyView(LoginRequiredMixin, View):
    login_url = '/login/'
    redirect_field_name = 'redirect_to'

構造繼承自LoginRequiredMixin類的子類,可以實現:

1. 驗證用戶是否登陸

2. 用戶登陸時和未登陸時分別跳轉的頁面,其中login_url字段定義的是用戶登陸時跳轉的頁面;redirect_field_name字段定義的是用戶未登錄時跳轉的頁面。

源碼:

class LoginRequiredMixin(AccessMixin):
    """
    CBV mixin which verifies that the current user is authenticated.
    """
    def dispatch(self, request, *args, **kwargs):
        if not request.user.is_authenticated:
            return self.handle_no_permission()
        return super(LoginRequiredMixin, self).dispatch(request, *args, **kwargs)

我們可以看出驗證用戶是否登陸的實現機制是調用is_authenticated屬性

其父類是AccessMixin,關注AccessMixin類中定義的get_login_url方法。

class AccessMixin(object):
    """
    Abstract CBV mixin that gives access mixins the same customizable
    functionality.
    """
    login_url = None
    permission_denied_message = ''
    raise_exception = False
    redirect_field_name = REDIRECT_FIELD_NAME

    def get_login_url(self):
        """
        Override this method to override the login_url attribute.
        """
        login_url = self.login_url or settings.LOGIN_URL
        if not login_url:
            raise ImproperlyConfigured(
                '{0} is missing the login_url attribute. Define {0}.login_url, settings.LOGIN_URL, or override '
                '{0}.get_login_url().'.format(self.__class__.__name__)
            )
        return force_text(login_url)

我們可以看出,上述的用戶登陸時重定向的頁面login_url的默認值爲None,用戶未登陸時重定向的頁面redirect_field_name = REDIRECT_FIELD_NAME。 並且REDIRECT_FIELD_NAME值爲

REDIRECT_FIELD_NAME = 'next'

login_url在get_login_url方法中定義爲:

login_url = self.login_url or settings.LOGIN_URL

由於登陸後重定向的地址一定是用戶中心,所以可以在項目配置文件中加上:

# 判斷用戶是否登陸後,指定未登錄用戶重定向的地址
LOGIN_URL = '/login/'

 

應用:

網站首頁-->用戶點擊個人中心-->後臺識別到用戶未登陸->重定向到login頁面->填寫完登陸信息後->重定向回到用戶希望請求到的個人中心頁面。

視圖views.py

class UserInfoView(LoginRequiredMixin, View):
    """用戶中心"""
    def get(self, request):
        """提供用戶中心頁面"""
        return render(request, 'user_center_info.html')

流程分析:

在用戶沒有登陸但是點擊用戶中心時,被重定向的請求地址爲

http://127.0.0.1:8000/login/?next=/info/

因此將用戶登陸類修改爲:

class LoginView(View):
    """用戶登陸"""

    def get(self, request):
        """提供用戶登陸頁面"""
        return render(request, 'login.html')

    def post(self, request):
        """實現用戶登陸邏輯"""
        # 接收參數
        username = request.POST.get('username')
        password = request.POST.get('password')
        remembered = request.POST.get('remembered')

        # 校驗參數
        if not all([username, password]):
            return http.HttpResponseForbidden('缺少必傳參數')

        # 校驗用戶名
        if not re.match(r'^[a-zA-Z0-9_-]{5,20}$', username):
            return http.HttpResponseForbidden('請輸入正確的用戶名或手機號')

        # 檢驗密碼
        if not re.match(r'^[0-9A-Za-z]{8,20}$', password):
            return http.HttpResponseForbidden('密碼最少8位,最長20位')
        # 認證用戶:使用賬號查詢用戶是否存在,如果用戶存在,再檢驗密碼是否正確
        # user = User.objects.get(username=username)
        # user.check_password()
        user = authenticate(username=username, password=password)
        if user is None:
            return render(request, 'login.html', {'account_errmsg': '賬號或密碼錯誤'})
        # 狀態保持
        login(request, user)
        if remembered != 'on':
            # 沒有記住登陸: 狀態保持在瀏覽器會話結束後就銷燬
            request.session.set_expiry(0)   # 單位是秒
        else:
            # 記住登陸:狀態保持週期爲兩週(默認是兩週)
            request.session.set_expiry(3600)

        # 響應結果
        # 先取出next
        next = request.GET.get('next')
        if next:
            # 重定向到next
            response = redirect(next)
        else:
            # 重定向到首頁
            response = redirect(reverse('contents:index'))

        # 爲了實現在首頁的右上角展示用戶名信息,我們需要將用戶名緩存到cookie中
        # response.set_cookie('key', 'value', 'expiry')
        response.set_cookie('username', user.username, max_age=3600)
        # 響應結果: 重定向到首頁
        return response

其中:

        # 響應結果
        # 先取出next
        next = request.GET.get('next')
        if next:
            # 重定向到next
            response = redirect(next)
        else:
            # 重定向到首頁
            response = redirect(reverse('contents:index'))

通過判定請求參數next是否爲空來判斷將來重定向的地址,如果爲空則重定向到主頁,否則根據next的值來進行重定向。

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章