根據官網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的值來進行重定向。