個人網站: lipeiguan.top 以後會慢慢轉移到個人網站, 歡迎大家收藏^ . ^ 寫在前面 我們在開發一個網站的時候, 經常需要實現網站的用戶系統. 這個時候我們需要實現用戶註冊、用戶登錄、用戶認證、註銷、修改密碼等一系列功能. 如果我們都是自己實現的話, 不是不可以, 只是有些浪費時間. ...
個人網站: lipeiguan.top
以後會慢慢轉移到個人網站, 歡迎大家收藏^ . ^
寫在前面
我們在開發一個網站的時候, 經常需要實現網站的用戶系統. 這個時候我們需要實現用戶註冊、用戶登錄、用戶認證、註銷、修改密碼等一系列功能. 如果我們都是自己實現的話, 不是不可以, 只是有些浪費時間.
而Django則內置了一個用戶認證系統 --> auth, 它預設使用 auth_user表來儲存用戶的數據.
那麼接下來就來瞭解一下這個強大的用戶認證系統.
auth模塊
導入auth
要使用這個模塊, 就需要先導入它.
from django.contrib import auth
auth模塊中的各種方法
authenticate()
- 驗證用戶名以及密碼是否正確
該函數提供了用戶認證功能, 一般需要username、password兩個關鍵字參數.
如果用戶名和密碼正確, 則會返回一個User對象, authenticate()會在該User對象上設置一個屬性來標識後端已經認證了該用戶, 而且該信息在後續的登錄過程中是需要的.
具體用法:
user = auth.authenticate(request, username="username", password="password")
login(HttpRequest, user)
- 登錄
該函數接受一個HttpRequest對象, 以及一個經過認證的User對象.
主要實現了一個用戶登錄的功能, 它會在後端為該用戶生成相關的session數據.
具體用法:
from django.shortcuts import render, redirect
from django.contrib import auth
def my_login(request):
if request.method == "POST":
username = request.POST.get("username")
password = request.POST.get("password")
user = auth.authenticate(request, username=username, password=password)
if user:
auth.login(request, user)
# Redirect to a success page.
else:
# Return an "invalid login" error message.
return render(request, "login.html")
logout(request)
- 註銷用戶
該函數接受一個HttpRequest對象, 無返回值.
當調用該函數時, 當前請求的session信息會全部清除. 該用戶即使沒有登錄, 使用該函數也不會報錯.
具體用法:
from django.authenticate import auth
def logout(request):
auth.logout(request)
# Redirect to a success page.
return redirect('/login/')
is_authenticated()
- 判斷當前請求是否通過了認證
如果一個頁面需要登錄才能訪問, 一個用戶在沒有登錄的情況下就訪問該頁面的話就會直接跳轉到登錄頁面, 之後在完成登錄之後, 會自動訪問跳轉之前的頁面.
具體用法:
def login(request):
if not request.user.is_authenticated();
return redirect("%s?next=%s" % (settings.LOGIN_URL, requedt.path))
Django也為我們設計好了一個用於該情況的裝飾器. 見 login_required()
login_required()
- 登錄校驗
auth給我們提供了一個裝飾器工具, 用來快捷的給某個視圖添加登錄校驗.
具體用法:
from django.contrib.auth.decorators import login_required
@login_required
def index(request):
...
若用戶沒有登錄, 則會跳轉到Django預設的登錄URL: 'accounts/login', 並傳遞當前訪問URL的絕對路徑(登錄成功後, 會重定向到該路徑).
當然, 我們可以自定義登錄的URL, 在settings.py文件中添加如下代碼
LOGIN_URL = '/login/'
create_user()
- 創建新用戶
auth提供的一個創建新用戶的方法, 需要提供必要參數(username、password)等.
具體用法:
from django.contrib.auth.models import User
user = User.objects.create_user(username="用戶名", password="密碼", email="郵箱(可以為空)", ...)
create_superuser()
- 創建超級用戶
auth提供一個創建新的超級用戶的方法, 需要提供必要參數(username, password)等.
具體用法:
from django.contrib.auth.models import User
user = User.objects.create_superuser(username="用戶名", password="密碼", email="郵箱", ...)
check_password(password)
- 檢查密碼是否正確
auth提供一個檢查密碼是否正確的方法, 需要提供當前請求用戶的密碼.
比如當用戶需要修改密碼時, 要輸入原來的密碼, 如果輸入的字元串通過了密碼檢查, 則返回 True, 否則返回 False.
具體用法:
ok = request.user.check_password("密碼")
set_password(password)
- 修改密碼
auth提供的一個修改密碼的方法, 接收 要設置的新密碼 作為參數.
註意: 設置完一定要調用用戶對象的save方法!!!
具體用法:
request.user.set_password("密碼")
request.user.save()
登錄、修改密碼、註冊、註銷功能示例
登錄:
def login(request):
if request.method == "POST":
username = request.POST.get("username")
password = request.POST.get("password")
user_obj = auth.authenticate(request, username=username, password=password)
if user_obj:
# 記錄登錄狀態
auth.login(request, user_obj)
next = request.GET.get("next")
if next:
return redirect(next)
return redirect('/index/')
return render(request, "login.html")
修改密碼:
@login_required
def set_password(request):
user = request.user
error_message = ""
if request.method == "POST":
old_password = request.POST.get("old_password") # 舊密碼
new_password = request.POST.get("new_password") # 新密碼
repeat_password = request.POST.get("repeat_password") # 重覆密碼
if user.check_password(old_password):
if not new_password:
error_message = "新密碼不能為空"
elif new_password != repeat_password:
error_message = "兩次密碼不一致"
else:
user.set_password(new_password)
user.save()
return redirect('/login/')
else:
error_message = "原密碼輸入有誤"
return render(request, "set_password.html", {"error_message": erroe_message})
return render(request, "set_password.html")
註冊:
def reg(request):
error_message = ""
if request.method == "POST":
username = request.POST.get("username")
password = request.POST.get("password")
repeat_password = request.POST.get("repeat_password")
if password:
if password != repeat_password:
error_message = "密碼輸入不一致"
else:
User.objects.create_user(username=username, password=password)
return redirect('/login/')
else:
error_message = "密碼不能為空"
return render(request, "reg.html")
註銷:
def logout(request):
auth.logout(request)
return redirect('/login/')
User對象的屬性
- id
- username: 用戶名
- password: 密碼
- email: 郵箱
- is_staff: 用戶是否擁有網站的管理許可權
- is_active: 是否允許用戶登錄. 設置為False, 可以在不刪除用戶的前提下禁止用戶登錄
- is_superuser: 是否是超級用戶
- last_login: 最後登錄時間
- first_name: 名
- last_name: 姓
date_joined
擴展預設的auth_user表
Django內置的認證系統很好用,但是提供的auth_user表的欄位只有那麼幾個, 如果需要增加幾個欄位該怎麼辦呢?
比如說想增加一個存儲用戶手機號的欄位, 就可以通過繼承內置的AbstractUser類, 來定義一個自己的Model類.
這樣既可以根據項目需求設計用戶表, 也可以使用Django的認證系統.
具體方法:
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
nid = models.AutoField(primary_key=True)
phone = models.CharField(max_length=11, null=True, unique=True)
def __str__(self):
return self.username
註意:
只是按照上面的方式擴展了內置的auth_user表之後還不夠, 還需要在settings.py文件中告訴Django, 我現在使用我定義的UserInfo表來做用戶認證.
在settings.py中添加如下代碼:
# 引用Django自帶的User表, 繼承時需要設置
AUTH_USER_MODEL = "app名.UserInfo"
註意:
一旦我們指定了新的認證系統所使用的表, 就需要重新在資料庫中創建表, 而不能繼續使用原來預設的auth_user表了.