1. 程式人生 > >Django2.0-驗證和授權(3)-User登陸,登出,登陸限制

Django2.0-驗證和授權(3)-User登陸,登出,登陸限制

登入、登出和登入限制

登入

在使用authenticate進行驗證後,如果驗證通過了。那麼會返回一個user物件,拿到user物件後,可以使用django.contrib.auth.login進行登入。

這裡使用的models是繼承自AbstractBaseUser的模型

# models.py

from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.contrib.auth.models import PermissionsMixin

class UserManager
(BaseUserManager): def _create_user(self, phone, username, password, **kwargs): # 這是一個受保護函式,只能被類自己中呼叫 # 作為create_user和create_superuser的被呼叫函式 if not phone: raise ValueError("必須傳遞手機號碼") if not password: raise ValueError("必須傳遞密碼") user =
self.model(phone=phone, username=username, **kwargs) # self.model表示當前模型 user.set_password(password) # password只能這樣設定 user.save() return user def create_user(self, phone, username, password, **kwargs): kwargs["is_superuser"] = False # 新增is_superuser鍵值對 return
self._create_user(phone=phone, username=username, password=password, **kwargs) def create_superuser(self, phone, username, password, **kwargs): kwargs["is_superuser"] = True return self._create_user(phone=phone, username=username, password=password, **kwargs) class InheritTwo(AbstractBaseUser, PermissionsMixin): phone = models.CharField(max_length=11, unique=True) username = models.CharField(max_length=20) password = models.CharField(max_length=20) address = models.CharField(max_length=100) is_active = models.BooleanField(default=True) USERNAME_FIELD = 'phone' REQUIRED_FIELDS = [] objects = UserManager() def get_full_name(self): return self.username def get_short_name(self): return self.username

配置settings.py中的AUTH_USER_MODEL='appname.InheritTwo',且為第一次資料庫遷移

html編寫

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Login</title>
</head>
<body>
<form action="" method="post">
    <input type="hidden" name="csrfmiddlewaretoken" value="{{ csrf_token }}">
    <table>
        <tbody>
        <tr>
            <td>登陸手機號:</td>
            <td><input type="text" name="phone"></td>
        </tr>
        <tr>
            <td>密碼:</td>
            <td><input type="password" name="password"></td>
        </tr>
        <tr>
            <td>
                <label for="">
                    <input type="checkbox" name="remember" value="1"> 記住我
                </label>
            </td>
            <td></td>
        </tr>
        <tr>
            <td></td>
            <td><input type="submit" value="登陸"></td>
        </tr>
        </tbody>
    </table>

</form>
</body>
</html>

登陸:

from django.shortcuts import render, redirect, reverse
from .forms import LoginForm
from django.contrib.auth import login, logout

def my_login(request):
    if request.method == "GET":
        return render(request, 'login.html')
    if request.method == "POST":
        form = LoginForm(request.POST)
        if form.is_valid():
            phone = form.cleaned_data.get("phone")
            password = form.cleaned_data.get("password")
            remember = form.cleaned_data.get("remember")

            user = authenticate(request, username=phone, password=password)
            # authenticate驗證
            if user and user.is_active:  # 如果存在且不為黑名單
				# 在session表中登記資訊
                login(request, user)
                if remember:  # 是否有點"記住我"
                    # 設定為None,則表示使用全域性的預設時間(2周)
                    request.session.set_expiry(None)
                else:
                	# 瀏覽器結束即結束
                    request.session.set_expiry(0)
				return HttpResponse("登陸成功")
            else:
                return HttpResponse("手機或密碼錯誤")
        else:
            return redirect(reverse('login'))

登出

登出,或者說退出登入。通過django.contrib.auth.logout來實現。他會清理掉這個使用者的session資料(表也會清除,類似request.session.flush())。

from django.contrib.auth import logout

def my_logout(request):
    logout(request)
    return HttpResponse("登出成功")

登入限制:使用裝飾器

需要某個檢視函式是需要經過登入後才能訪問的。

通過django.contrib.auth.decorators.login_required裝飾器來實現。

from django.contrib.auth.decorators import login_required

@login_required(login_url='/login/')  # 如果驗證失敗,則跳轉login_url指定的頁面
# 會傳遞 next= urls.py中檢視函式對應的urls路徑
# 比如當前函式的urls路徑為 two/profile/ 則傳遞 next=/two/prifle/  <-!!!沒有多一個 /
def profile(request):
    return HttpResponse("登陸成功才能看見")

/login/的檢視函式中,判斷是否有這個next查詢字串,決定是否再跳轉到profile檢視函式

def my_login(request):
    # ...
    if user and user.is_active:  # 如果存在且不為黑名單
        # request.session['user_id'] = user.id
        login(request, user)
        if remember:
            # 設定為None,則表示使用全域性的預設時間(2周)
            request.session.set_expiry(None)
            else:
                request.session.set_expiry(0)
                next_url = request.GET.get('next')  # 裝飾器login_request修飾的函式跳轉後會傳遞next查詢字串
                if next_url:
                    return redirect(next_url)  # 跳轉回profile檢視函式
                else:
                    return HttpResponse("登陸成功")
                else:
                    return HttpResponse("手機或密碼錯誤")
    # ...