Django 內置一個 auth
模塊,幫助用戶實現注冊、登錄、注銷以及修改密碼等功能,幫助開發者省去了很多功夫。
auth 模塊
在創建模型時,Django內部會生成一個名為 auth_user
的數據表,用於存儲認證的用戶信息。
auth
模塊提供了一系列的方法,使用之前需要導入:
from django.contrib import auth
authenticate() 方法
提供用戶認證功能,驗證用戶名和密碼是否正確等。如驗證成功,則返回一個 User
對象。
from django.contrib import auth
def login(request):
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 用戶認證,驗證用戶名、密碼是否正確,並返回一個 user 對象
# username、password 字段對應 auth_user 表中相應字段
user_obj = auth.authenticate(username=username, password=password)
login() 方法
實現用戶登錄功能,會在后台為登錄用戶生成 session
數據。
from django.contrib import auth
auth.login(request, user_obj)
from django.contrib.auth import login
login(request, user_obj)
接收兩個參數,第一個為 HTTPRequest
對象,以及一個認證過的用戶對象(即 authenticate()
認證過的用戶對象)。
from django.contrib import auth
def login(request):
"""登錄"""
if request.method == 'POST':
username = request.POST.get('username')
password = request.POST.get('password')
# 用戶認證,驗證用戶名、密碼是否正確,並返回一個 user 對象
user_obj = auth.authenticate(username=username, password=password)
if user_obj:
# 將驗證成功的用戶封裝到 request.user 對象中
auth.login(request, user_obj)
return redirect('home')
else:
return '錯誤信息'
return render(request, 'login.html')
認證成功的用戶對象,執行 login()
方法,實現登錄功能,否則返回錯誤信息。
Tips
執行過 login()
方法的用戶對象,就能通過request.user
拿到當前登錄的用戶對象,從而取出用戶的相關信息,否則取得的將是一個匿名用戶對象 AnonymounsUser Object
。
login(request, user_obj)
# 獲得當前登錄用戶對象
user = request.user
# 獲得當前登錄用戶對象的用戶名
username = request.user.username
logout() 方法
該方法實現注銷功能,清除當前登錄用戶數據庫中的 session
數據,接收一個 HttpRequest
對象,無返回值。
from django.contrib import auth
def logout(request):
"""注銷"""
auth.logout(request)
# 注銷后重定向到登錄頁面
return redirect('login')
is_authenticated 屬性
判斷當前用戶是否通過認證,為布爾值。
def home(request):
"""首頁"""
ret = request.user.is_authenticated
print(ret) # True
login_required() 方法
auth 模板提供的一個裝飾器工具,能夠便捷地為某個視圖添加登錄校驗。
- 若用戶沒有登錄,則默認會跳轉到
accounts/login/
,並傳遞當前訪問 url 絕對路徑。 - 自定義跳轉路徑,只需在
settings.py
中添加:
# 當用戶沒有登錄,訪問某個視圖時將會跳轉到登錄頁面
LOGIN_URL = '/login/'
from django.contrib.auth.decorators import login_required
# 添加裝飾器
@login_required
def home(request):
"""首頁"""
return render(request, 'home.html')
當用戶訪問 home
頁面時,若沒有登錄則會跳轉到登錄頁面,否則返回 home
頁面。
用戶相關
上面介紹的都是關於登錄相關的,下面將介紹如何創建在 auth_user
中創建用戶,修改密碼,驗證密碼等。
create_superuser() 方法
該方法用於創建一個超級用戶,接收 username、password
兩個必要參數。效果與執行 python manage.py createsuperuser
等同。
from django.contrib.auth.models import User
user_obj = User.objects.create_superuser(username='用戶名',password='密碼',email='郵箱',...)
create_user() 方法
一般情況 create_superuser()
方法很少使用,最常使用的是create_user()
方法,它將會創建一個普通用戶,常應用於注冊視圖中。
創建用戶所需字段,應與 auth_user
數據表中字段對應。
from django.contrib.auth.models import User
def signup(request):
# 創建新用戶
user_obj = User.objects.create_user(username='lila', password='1234')
return HttpResponse('創建成功')
Tips
新創建的用戶,保存在 auth_user
數據表中的密碼是經過加密的。
check_password() 方法
檢查登錄用戶密碼是否正確,需要當前請求用戶的密碼。
from django.contrib.auth.models import User
def signup(request):
# 創建新用戶
user_obj = User.objects.create_user(username='lila', password='1234')
ret = user_obj.check_password('123456')
print(ret) # False
return HttpResponse('創建成功')
密碼正確返回 True,否則返回 False。
或者對當前請求的 user 對象校驗原密碼是否正確:
obj = request.user.check_password(raw_password='原始密碼')
set_password() 方法
該方法用於修改密碼,接收要新密碼作為參數,最后一定要執行 save()
方法保存,否則無效。
def set_password(request):
"""
修改密碼,request.user 中封裝了已認證且執行了登錄功能的用戶對象
:param request:
:return:
"""
request.user.set_password('12')
password = request.user.password
request.user.save()
print(password)
return HttpResponse('修改成功')
修改密碼示例
該示例僅適用於已登錄的用戶,在內部修改密碼,未登錄的用戶將跳轉到登錄頁面。
from django.shortcuts import render, redirect, HttpResponse
from django.contrib.auth.decorators import login_required
@login_required
def set_password(request):
"""
修改密碼,request.user 中封裝了已認證且執行了登錄功能的用戶對象
:param request:
:return:
"""
user = request.user
ret = {'message': None}
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:
ret['message'] = '新密碼不能為空'
elif new_password != repeat_password:
ret['message'] = '兩次密碼輸入不一致'
else:
user.set_password(new_password)
user.save()
return redirect('login')
else:
ret['message'] = '原密碼不正確'
return render(request, 'set_password.html', ret)
auth 模塊拓展
由於 auth 模板中 auth_user
數據表字段是固定的,因此當我們使用 auth 模塊,想要添加額外的字段時,就需要對其進行拓展。
拓展方法有兩種:
- 模型中新增一個表,與
auth_user
表一對一關聯 - 繼承內置的
AbstractUser
類:常用
- 模型
models.py
中新建一個類,繼承自AbstractUser
:
from django.contrib.auth.models import User, AbstractUser # 導入 AbstractUser 類
class UserInfo(AbstractUser):
"""
繼承 AbstractUser
新增字段:phone、addr
"""
phone = models.CharField(max_length=11, verbose_name='手機號碼')
addr = models.CharField(max_length=128, verbose_name='家庭地址')
- 配置
settings.py
新增的類繼承 AbstractUser
,拓展后將會覆蓋 auth_user
表,因此需要配置 settings
,使默認認證知道要使用哪種表認證。
# settings.py
# 在最后添加如下代碼
AUTH_USER_MODEL = 'app名.新增的類名'
AUTH_USER_MODEL = 'app.UserInfo' # 示例
- 遷徙數據表
python manage.py makemigrations
python manage.py migrate
- 創建用戶
拓展 auth 模塊后,使用的不再是原來 auth_user
表,而是新表 app.UserInfo
表,因此在創建用戶時應該注意。
# 拓展之前
from django.contrib.auth.models import User
user_obj = User.objects.create_user(username='lila', password='1234')
# 拓展之后
from app.models import UserInfo
user_obj = UserInfo.objects.create_user(username='lila', password='1234')
Tips
- 若已經遷徙了模型,拓展 auth 模塊時,需要將
migrations
文件夾下文件(如:0001_initial.py
文件刪除),否則會報ValueError: Related model u'app.model' cannot be resolved
。 - 若還沒有遷徙模型,那么正常執行即可。