我們在開發一個網站的時候,無可避免的需要設計實現網站的用戶系統。此時我們需要實現包括用戶注冊、用戶登錄、用戶認證、注銷、修改密碼等功能,如果這些過程都需要我們手動實現,過程着實麻煩。
而Django是一個完美主義的終極框架,在這個問題上,內置了一個強大的用戶認證系統--auth,使用默認創建的auth_user來存儲用戶數據,如果我們使用auth模塊來進行用戶認證,那么也需要使用django默認創建好的auth_user表來存儲用戶的信息數據。
在視圖函數中引用django的auth功能,先導入
from django.contrib import auth
注意:auth_user並不是我們在models.py文件中定義的模型,而是django里面自帶的應用中的models.py文件生成的。所以我們用的時候需要先同步一下數據庫。
makemigrations
migrate
創建一個用戶
往auth_user中添加數據的命令,在項目路徑下執行如下命令。
python manage.py createsuperuser # 要通過這個指令來創建用戶,因為這個指令會將你的密碼加密
或者在django的命令行下,也就是同步數據的那個命令行執行
createsuperuser # 創建一個超級用戶
創建成功后,在auth_user表中就有數據了,目前我們只需要關注username和password。
Django中的后台管理
其實auth_user本質是django內置的后台管理數據表而使用的帳號管理表。
我們啟動項目,然后訪問http://127.0.0.1:8000/admin/就可以通過剛才的帳號登錄這個管理系統。
登錄后,進入的頁面是管理django項目的數據表的可視化頁面,類似navicat,只不過這個是django提供的網頁版。
User表中字段
內置auth引用創建的User模型中有以下字段:
- username: 用戶名。150個字符以內。可以包含數字和英文字符,以及_、@、+、.和-字符。不能為空,且必須唯一!
- first_name:歪果仁的first_name,在30個字符以內。可以為空。
- last_name:歪果仁的last_name,在150個字符以內。可以為空。
- email:郵箱。可以為空。
- password:密碼。經過哈希過后的密碼。
- groups:分組。一個用戶可以屬於多個分組,一個分組可以擁有多個用戶。groups這個字段是跟Group的一個多對多的關系。
- user_permissions:權限。一個用戶可以擁有多個權限,一個權限可以被多個用戶所有用。和Permission屬於一種多對多的關系。
- is_staff:是否可以進入到admin的站點。代表是否是員工。這個字段如果不使用admin的話,可以自行忽略,不影響使用
- is_active:是否是可用的。對於一些想要刪除賬號的數據,我們設置這個值為False就可以了,而不是真正的從數據庫中刪除。
- is_superuser:是否是超級管理員。如果是超級管理員,那么擁有整個網站的所有權限。
- last_login:上次登錄的時間。
- date_joined:賬號創建的時間。
2.auth模塊的方法
authenticate()
提供了用戶認證功能,即驗證用戶名以及密碼是否正確,一般需要username 、password兩個關鍵字參數,而user表中用戶名和密碼的字段名稱就是username和password。
語法:
user = auth.authenticate(username='user',password='password')
authenticate方法如果認證成功(用戶名和密碼正確有效,就是去auth_user表中查詢一下是否存在這條記錄),便會返回一個 User 對象,查詢認證失敗返回None。
login(HttpRequest,user)
該函數接受一個HttpRequest對象,以及一個經過認證的User對象。
auth.login方法執行會做的兩件事:
-
完成session的事情,將用戶數據存入數據庫,生成隨機sessionid存在cookie中發送給客戶端。
-
request.user=user_obj,將驗證后的用戶對象存在request請求對象中的user中
只要使用login(request, user_obj)之后,request.user就能拿到當前登錄的用戶對象。否則request.user得到的是一個匿名用戶對象(AnonymousUser Object,是request.user的默認值)
查看用戶狀態
login使用之前,查看user信息
request.user # 沒有經過login方法來封裝用戶的信息,那么這個顯示的是一個匿名用戶 request.user.id # None request.user.username # 空字符串 request.user.is_active # False
login使用之后,查看user信息
request.user # request.user對象是全局的,是當前登陸的user對象,並且可以在模板語言里面直接使用{{ request.user.username }},萬能的句點號 request.user.id # 1 用戶賬號在表中的id值。 request.user.username # ryxiong request.user.is_active # True
logout(request)
該函數接受一個HttpRequest對象,無返回值。
當調用該函數時,當前請求的session信息會全部清除。即使沒有登錄,使用該函數也不會報錯。
用法:
from django.contrib.auth import logout def logout(request): logout(request) # 其實內部就是執行了request.session.flush() Redirect to a success page.
3.使用auth_user登錄
使用auth_user表來驗證用戶登錄
from django.shortcuts import render,HttpResponse,redirect from app01 import models from django.contrib import auth # 導入django的auth模塊 def login(request): if request.method=="GET": return render(request,"login.html") else: username = request.POST.get("username") password = request.POST.get("password") user_obj = auth.authenticate(username=username,password=password) # 這里auth模塊拿到用戶名和密碼后,會去auth_user表中查找數據,如果存在返回用戶對象,不存在返回None if user_obj: auth.login(request,user_obj) # 1.auth.login做了session的事情,將用戶數據存入數據庫,生成sessionid存在cookie中 # 2.request.user=user_obj,將用戶對象存在請求中的user中。 return HttpResponse("登錄成功") else: return redirect("login")
登錄頁面login.html
<form action="{% url 'login' %}" method="post"> 用戶名:<input type="text" name="password"> 密碼:<input type="password" name="password"> <input type="submit"> </form>
二、User對象使用
1.user對象的方法
is_authenticated()
如果是真正的 User 對象,返回值恆為 True 。 用於檢查用戶是否已經通過了認證。
通過認證並不意味着用戶擁有任何權限,甚至也不檢查該用戶是否處於激活狀態,這只是表明用戶成功的通過了認證。
這個方法很重要, 在后台用request.user.is_authenticated()判斷用戶是否已經登錄,如果true則可以向前台展示request.user.name。
request.user.is_authenticated() # 驗證合法返回True,否則返回False
login_required()
auth 給我們提供的一個裝飾器工具,用來快捷的給某個視圖添加登錄校驗。
用法:
from django.contrib.auth.decorators import login_required @login_required def home(request): return redirecter("login")
用戶登錄使用實例
-
用戶登陸后才能訪問某些頁面,
-
如果用戶沒有登錄就訪問該頁面的話直接跳到登錄頁面
-
用戶在跳轉的登陸界面中完成登陸后,自動訪問跳轉到之前訪問的地址
方法一:通過is_authenticated方法驗證
from 項目名 import settings def home(request): if request.user.is_authenticated(): return render(request,'home.html') else: return redirect('%s?next=%s' % (settings.LOGIN_URL, request.path))
方法二:通過django自帶裝飾器驗證
auth 給我們提供的一個裝飾器工具,用來快捷的給某個視圖添加登錄校驗。
from django.contrib.auth.decorators import login_required @login_required def home(request): return render(request,'home.html')
若用戶沒有登錄,則會跳轉到django默認的 登錄URL '/accounts/login/ ' 並傳遞當前訪問url的絕對路徑 (登陸成功后,會重定向到該路徑)。
如果需要重定向到自定義登錄的URL,則需要在settings.py文件中通過LOGIN_URL進行修改。
LOGIN_URL = '/login/'
create_user()
auth 提供的一個創建新用戶的方法,需要提供必要參數(username、password)等。
用法:
from django.contrib.auth.models import User def register(request): user = User.objects.create_user(username='用戶名',password='密碼',email='郵箱',...) return HttpResponse("注冊成功")
check_password(raw_password)(了解)
auth 提供的一個檢查密碼是否正確的方法,需要提供當前請求用戶的密碼。密碼正確返回True,否則返回False。
用法:校驗密碼
ok = user_obj.check_password('密碼')
直接針對當前請求的user對象校驗原密碼是否正確
ok = request.user.check_password(raw_password='原密碼')
set_password(raw_password)
auth提供的一個修改密碼的方法,接收要設置的新密碼作為參數。
注意:設置完一定要調用用戶對象的save方法!!!
user_obj.set_password('新密碼') #user_obj其實就是request.user user_obj.save() #request.user.save()
使用實例
def set_password(request): request.user.set_password(666) # 設置用戶密碼 request.user.save() # 保存到數據庫 return redirect('login')
2.user對象的屬性
user_obj能夠拿到認證所用用戶表的數據屬性,比如username, password等。
常用屬性:
-
is_staff : 用戶是否擁有網站的管理權限.
-
is_active : 是否允許用戶登錄, 設置為 False,可以在不刪除用戶的前提下禁止用戶登錄。
三、擴展默認的auth_user表
1.擴展auth_user表方法
當我們想使用內置系統,但是auth_user表中的字段都是固定的,我們在項目中沒法拿來直接使用。這個時候我們可以擴展auth_user表來使用。
擴展auth_user表共有兩種方法:
-
新建一張表,通過一對一的方式與內置的auth_user表關聯。
-
繼承內置的AbstractUser類,定義一個自己的Model類,django會給我們自動創建一張user表,這張表可以使用auth模塊。
通過繼承來擴展auth_user表
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
注意:
-
UserInfo表里不需要有auth_user里重復的字段,如username和password,但是可以直接使用這些字段,並且Django會自動將password加密。
-
按上述方法擴展內置的auth_user表后,一定要在settings.py中配置,讓Django使用我們新定義的UserInfo表用戶認證。
# 引用Django自帶的User表,繼承使用時需要設置,這樣django就知道從我們的app名的應用下的models文件中去查找UserInfo這張表了
AUTH_USER_MODEL = "app名.UserInfo"
自定義認證系統默認使用的數據表之后,我們就可以像使用默認的auth_user表那樣使用我們的UserInfo表進行django中的認證。
創建普通用戶
models.UserInfo.objects.create_user(username='用戶名', password='密碼')
創建超級用戶
models.UserInfo.objects.create_superuser(username='用戶名', password='密碼')