Django auth組件
Django auth
Django
中的auth
組件非常適合高效開發,它會用自帶的auth_user
表來記錄用戶相關的數據。
並且提供了一整套服務,包括判斷用戶是否登錄,session
限制頁面訪問,創建用戶,註銷用戶等等。
通過以下程式碼即可導入auth
組件。
from django.contrib import auth
使用auth
組件前,一定要切記生成物理表。
python manage.py migrate
此外,注意一點:
auth
表中的數據和admin
後台管理是相通的。
我們可以看一下這張表中的欄位資訊。
id 主鍵
username 用戶名
password 密碼(sha256加密)
last_login 上次登錄時間
is_superuser 是否是管理員
first_name 姓
last_name 名
email 郵箱地址
is_staff 是否是工作人員
is_activ 是否激活
date_joined 加入日期
登錄相關
authenticate
驗證用戶名及密碼是否正確,最少兩個參數,即username
和password
。
返回值是一條記錄對象,並且該對象上會設置一個屬性來標識該用戶已經通過認證。
user_obj = auth.authenticate(request,username=username,password=password) # request選填
login
該方法能夠將authenticate()
返回的用戶對象存入至request
對象中,通過request.user
即可調用出當前對象。
並且該方法還會自動生成一個session
保存至session
表中。
只要使用
login(request, user_obj)
之後,request.user
就能拿到當前登錄的用戶對象。否則
request.user
得到的是一個匿名用戶對象(AnonymousUser Object
)。
class Login(View):
def get(self, request):
return render(request, "login.html")
def post(self, request):
username = request.POST.get("username")
password = request.POST.get("password")
user_obj = auth.authenticate(
username=username, password=password) # 拿到用戶記錄對象
if user_obj:
auth.login(request, user_obj) # 封裝對象至request中,並且添加session
return redirect("/index/")
else:
return redirect("/register/") # 跳轉到註冊頁面
logout
該方法接受一個HttpRequest
對象,無返回值。
當調用該函數時,當前請求的session
資訊會全部清除。該用戶即使沒有登錄,使用該函數也不會報錯。
class Logout(View):
def get(self, request):
auth.logout(request) # 清除session
return HttpResponse("清除成功")
is_authenticated
該方法判斷用戶是否進行登錄,返回布爾值。
{% if request.user.is_authenticated %} <!-- 前端不需要加括弧 -->
<a class="btn btn-default" href="{% url 'edit_password' %}'" role="button">修改{{request.user.username}}密碼</a>
{% endif %}
login_requierd
auth
組件給我們提供的一個裝飾器工具,用來快捷的給某個視圖添加登錄校驗。
需要先導入該裝飾器:
from django.contrib.auth.decorators import login_required
使用方法:單獨指定跳轉的視圖函數
@method_decorator(login_required(login_url='/login/'),name="dispatch")
class Logout(View):
def get(self, request):
auth.logout(request) # 清除session
return HttpResponse("清除成功")
或者你也可以使用全局配置,讓他自動跳轉到某一功能下。
局部裝飾器跳轉比全局跳轉優先順序要高
LOGIN_URL = '/login/' # 這裡配置成你項目登錄頁面的路由
註冊相關
create_user
創建一個普通用戶。需要提供必要參數(username、password)等
注意:我們要先導入auth_user
表才行,此外,所有創建用戶等密碼都是密文。
from django.contrib.auth.models import User
class Register(View):
def get(self, request):
return render(request, "register.html")
def post(self, request):
username = request.POST.get("username")
password = request.POST.get("password")
repeat_password = request.POST.get("repeat-password")
if repeat_password == password:
if User.objects.filter(username="username").exists(): # 如果表中不存在該數據時
User.objects.create_user(
username = username,
password = password,
)
return redirect("/index/")
else:
return HttpResponse("用戶已存在")
else:
return HttpResponse("密碼不一致,請重新輸入")
create_superuser
創建一個超級用戶。需要提供必要參數(username、password、email)等
注意:創建超級用戶一般會使用命令行創建,不要使用程式碼進行創建。
from django.contrib.auth.models import User
user_obj = User.objects.create_superuser(username='用戶名',password='密碼',email='郵箱',...)
修改密碼
check_password
需要一個參數,即老密碼。判斷老密碼是否輸入正確
set_password
設置密碼,接收要設置的新密碼作為參數。
注意:設置完一定要調用用戶對象的
save()
方法!!!
@method_decorator(login_required(login_url='/login/'),name="dispatch")
class edit_password(View):
def get(self, request):
return render(request, "edit_password.html",locals())
def post(self, request):
username = request.POST.get("username")
old_password = request.POST.get("old_password")
new_password = request.POST.get("new_password")
user_obj = request.user
if user_obj.check_password(old_password): # 驗證老密碼是否正確
user_obj.set_password(new_password) # 設置密碼
user_obj.save()
auth.login(request, user_obj) # 重新封裝對象至request中,並且添加session
return redirect("/index/")
else:
return HttpResponse("密碼錯誤")
其他屬性
屬性 | 描述 |
---|---|
user_obj.is_staff | 用戶是否擁有網站的管理許可權. |
user_obj.active | 是否允許用戶登錄, 設置為 False,可以在不刪除用戶的前提下禁止用戶登錄。 |
擴展auth_user
我們可以通過繼承內置的 AbstractUser
類,來定義一個自己的Model
類。
這樣就可以擴展auth_user
表中的欄位了。
注意:這必須是在沒執行
python manage.py migrate
之前
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
表來做用戶認證。寫法如下:
# 引用Django自帶的User表,繼承使用時需要設置
AUTH_USER_MODEL = "app名.UserInfo(表名)"
自定義認證系統默認使用的數據表之後,我們就可以像使用默認的auth_user
表那樣使用我們的UserInfo
表了
創建普通用戶:
UserInfo.objects.create_user(username='用戶名', password='密碼')
創建超級用戶:
UserInfo.objects.create_superuser(username='用戶名', password='密碼')
一旦我們指定了新的認證系統所使用的表,我們就需要重新在資料庫中創建該表,而不能繼續使用原來默認的
auth_user
表了。
全套程式碼
最終效果
路由層
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^index/', views.Index.as_view(), name='index'),
url(r'^login/', views.Login.as_view(), name='login'),
url(r'^logout/', views.Logout.as_view(), name='logout'),
url(r'^register/', views.Register.as_view(), name='register'),
url(r'^edit_password/', views.edit_password.as_view(), name='edit_password'),
url(r'^other/', views.Other.as_view(), name='other'),
]
視圖函數
from django.shortcuts import render
from django.shortcuts import redirect
from django.shortcuts import HttpResponse
from django.views import View
from django.views.decorators.csrf import csrf_exempt, csrf_protect
from django.utils.decorators import method_decorator
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.contrib.auth.models import User
# Create your views here.
class Index(View):
def get(self, request):
return render(request, "index.html",locals())
class Login(View):
def get(self, request):
return render(request, "login.html")
def post(self, request):
username = request.POST.get("username")
password = request.POST.get("password")
user_obj = auth.authenticate(
username=username, password=password) # 拿到用戶記錄對象
if user_obj:
auth.login(request, user_obj) # 封裝對象至request中,並且添加session
return redirect("/index/")
else:
return redirect("/register/") # 跳轉到註冊頁面
@method_decorator(login_required(login_url='/login/'),name="dispatch")
class Logout(View):
def get(self, request):
auth.logout(request) # 清除session
return HttpResponse("清除成功")
class Register(View):
def get(self, request):
return render(request, "register.html")
def post(self, request):
username = request.POST.get("username")
password = request.POST.get("password")
repeat_password = request.POST.get("repeat-password")
if repeat_password == password:
if not User.objects.filter(username=username): # 如果表中不存在該數據時
User.objects.create_user(
username = username,
password = password,
)
return redirect("/index/")
else:
return HttpResponse("用戶已存在")
else:
return HttpResponse("密碼不一致,請重新輸入")
@method_decorator(login_required(login_url='/login/'),name="dispatch")
class edit_password(View):
def get(self, request):
return render(request, "edit_password.html",locals())
def post(self, request):
username = request.POST.get("username")
old_password = request.POST.get("old_password")
new_password = request.POST.get("new_password")
user_obj = request.user
if user_obj.check_password(old_password): # 驗證老密碼是否正確
user_obj.set_password(new_password) # 設置密碼
user_obj.save()
auth.login(request, user_obj) # 重新封裝對象至request中,並且添加session
return redirect("/index/")
else:
return HttpResponse("密碼錯誤")
@method_decorator(login_required(login_url='/login/'),name="dispatch")
class Other(View):
def get(self, request):
if not request.user.is_authenticated():
return redirect("/login/")
else:
return HttpResponse("歡迎來到其他頁面")
模板層
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
<script src='//cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
<script src='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
<h1>歡迎來到主頁</h1>
<a class="btn btn-primary" href="{% url 'login' %}" role="button">登錄</a>
<a class="btn btn-warning" href="{% url 'register' %}" role="button">註冊</a>
{% if request.user.is_authenticated %}
<a class="btn btn-default" href="{% url 'edit_password' %}'" role="button">修改{{request.user.username}}密碼</a>
<a class="btn btn-danger" href="{% url 'logout' %}" role="button">註銷</a>
{% endif %}
</body>
</html>
edit_password.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
<script src='//cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
<script src='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
<form action="" method="POST" role="form">
{% csrf_token %}
<legend>修改密碼</legend>
<div class="form-group">
<label for="username">用戶名</label>
<input type="text" class="form-control" id="username" name="username" placeholder="用戶名" value="{{request.user.username}}" readonly>
</div>
<div class="form-group">
<label for="old_password">舊密碼</label>
<input type="password" class="form-control" id="old_password" name="old_password" placeholder="密碼">
</div>
<div class="form-group">
<label for="new_password">新密碼</label>
<input type="password" class="form-control" id="new_password" name="new_password" placeholder="密碼">
</div>
<button type="submit" class="btn btn-primary">提交</button>
</form>
</body>
</html>
login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
<script src='//cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
<script src='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
<form action="" method="POST" role="form">
{% csrf_token %}
<legend>登錄用戶</legend>
<div class="form-group">
<label for="username">用戶名</label>
<input type="text" class="form-control" id="username" name="username" placeholder="用戶名">
</div>
<div class="form-group">
<label for="password">密碼</label>
<input type="text" class="form-control" id="password" name="password" placeholder="密碼">
</div>
<button type="submit" class="btn btn-primary">登錄</button>
</form>
</body>
</html>
register.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link href='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css' rel='stylesheet'>
<script src='//cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js'></script>
<script src='//cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js'></script>
</head>
<body>
<form action="" method="POST" role="form">
{% csrf_token %}
<legend>註冊用戶</legend>
<div class="form-group">
<label for="username">用戶名</label>
<input type="text" class="form-control" id="username" name="username" placeholder="用戶名">
</div>
<div class="form-group">
<label for="password">密碼</label>
<input type="text" class="form-control" id="password" name="password" placeholder="密碼">
</div>
<div class="form-group">
<label for="repeat-password">確認</label>
<input type="text" class="form-control" id="repeat-password" name="repeat-password" placeholder="重複輸入密碼">
</div>
<button type="submit" class="btn btn-primary">註冊</button>
</form>
</body>
</html>