django框架之auth模塊
內容回顧
1. form表單組件
1. 常用字段
1. CharField()
2. ChoiceField()
2. 參數或配置
1. label="label標簽顯示的文本內容"
2. initial="默認值"
3. widget=forms.widgets.TextInput() --> <input typle=‘text‘/>
widget=forms.widgets.PasswordInput(
attrs={"class": "c1", "s12": "hao"}
)
4. required=False --> is_valid()校驗的時候該字段沒有值也不報錯
5. error_messages={"required": "xx字段不能為空", "max_length": "xx字段最多不能超過位數"}
6. max_length
7. min_length
8. validators=[驗證器1,驗證器2, ...]
3. 驗證器
1. 內置正則驗證
from django.core.validators import RegexValidator
validators=[RegexValidator(r‘^1[3-9]\d{9}$‘, "手機號碼格式不正確!"), ]
2. 自定義方法實現
from django.core.exceptions import ValidationError
# 自定義校驗的方法
def name_check(value):
if ‘西遊記‘ in value:
raise ValidationError("不符合社會主義核心價值觀!")
else:
return value
validators=[name_check, ],
4. 鉤子函數
0. self.cleaned_data --> 用來存放經過驗證數據的大字典
self.add_error("字段名", "錯誤提示信息")
1. 局部鉤子(Hook)
通過自定義一個clean_字段名的方法實現字段的校驗
2. 全局鉤子
此時 每個字段獨立的校驗都走完了,cleaned_data中已經存放著所有字段的數據
def clean(self):
print("我可是看過源碼的人,我知道你肯定會執行這個方法!")
# 重寫父類的clean方法
# 該clean方法, 在每個字段都校驗通過之後才調用執行
pwd = self.cleaned_data.get("pwd")
re_pwd = self.cleaned_data.get("re_pwd")
if re_pwd and re_pwd == pwd:
# 確認密碼和密碼相同, 正常
return self.cleaned_data
else:
# 確認密碼和密碼不同
self.add_error(‘re_pwd‘, "兩次密碼不一致") # ?
raise ValidationError("兩次密碼不一致")
今日內容:
Django自帶的用戶認證:
我們在開發一個網站的時候,無可避免的需要設計實現網站的用戶系統。此時我們需要實現包括用戶註冊、用戶登錄、用戶認證、註銷、修改密碼等功能,這還真是個麻煩的事情呢。
Django作為一個完美主義者的終極框架,當然也會想到用戶的這些痛點。它內置了強大的用戶認證系統--auth,它默認使用 auth_user 表來存儲用戶數據。
auth模塊:
首先執行數據庫遷移的兩條命令,然後再數據庫中會有這樣一個表,author_user,這是django自帶的一個用戶表。
通過django創建超級用戶:
python manage.py createsuperuser
authenticate() :
提供了用戶認證功能,即驗證用戶名以及密碼是否正確,一般需要username 、password兩個關鍵字參數。
如果認證成功(用戶名和密碼正確有效),便會返回一個 User 對象。
authenticate()會在該 User 對象上設置一個屬性來標識後端已經認證了該用戶,且該信息在後續的登錄過程中是需要的。
用法:
login(HttpRequest, user)
該函數接受一個HttpRequest對象,以及一個經過認證的User對象。
該函數實現一個用戶登錄的功能。它本質上會在後端為該用戶生成相關session數據。
我們寫一個登陸認證的例子:
我們在認證的時候,因為author_user是django自帶的表,所以我們沒辦法用 models.類名 去數據庫裏面查詢username和password,這時候就要:
from django.contrib import auth
def login(request):
err_msg = ‘‘
if request.method == ‘POST‘:
username = request.POST.get(‘username‘)
password = request.POST.get(‘pwd‘)
# username 和password 都匹配成功就返回一個user對象.
user = auth.authenticate(username=username, password=password)
if user:
#用戶名 密碼正確
# 1 讓當前用戶登錄,給session和cookie寫入數據
auth.login(request,user)
return redirect(request,‘index.html’)
else:
#用戶名或密碼錯誤
err_msg = ‘用戶名或密碼錯誤‘
return render(request,‘login.html‘,{‘err_msg‘:err_msg})
logout(request) :
該函數接受一個HttpRequest對象,無返回值。
當調用該函數時,當前請求的session信息會全
def logout(request): #註銷 auth.logout(request) return redirect(‘/login/‘)
這樣就清楚了session數據。
login_requierd():
現在如果我們直接輸入index頁面的網址,也是可以直接訪問的。這顯然不是我們想要的,我們需要先登陸然後再進入index頁面。
auth 給我們提供的一個裝飾器工具,用來快捷的給某個視圖添加登錄校驗。
from django.contrib.auth.decorators import login_required @login_required def index(request): return render(request,‘index.html‘)
若用戶沒有登錄,則會跳轉到django默認的 登錄URL ‘/accounts/login/ ‘ 並傳遞當前訪問url的絕對路徑 (登陸成功後,會重定向到該路徑)。
如果需要自定義登錄的URL,則需要在settings.py文件中通過LOGIN_URL進行修改。
LOGIN_URL = ‘/login/‘ # 這裏配置成你項目登錄頁面的路由
is_authenticated():
用來判斷當前請求是否通過了認證。
def index(request): #用來判斷當前請求是否通過了認證。 print(request.user,request.user.is_authenticated()) return render(request,‘index.html‘)
現在我們寫一個註冊,利用之前學過的form表單,讓用戶去填寫,然後拿用戶的信息在試圖的函數中認證登陸。
創建一個forms文件夾:
from django import forms class RegForm(forms.Form): username = forms.CharField( label=‘用戶名‘, ) password = forms.CharField( label=‘密碼‘, widget = forms.widgets.PasswordInput() ) re_password = forms.CharField( label=‘確認密碼‘, widget = forms.widgets.PasswordInput() )
views.py代碼:
from app01 import forms def register(request): form_obj = forms.RegForm() if request.method == ‘POST‘: from_obj = forms.RegForm(request.POST) 。。。 return render(request,‘register.html‘,{‘form_obj‘:form_obj})
html代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>註冊</title> </head> <body> <form action="/register/"> {% csrf_token %} {# {{ form_obj.as_p }}#} <div> <label for="{{ form_obj.username.id_for_label }}">{{ form_obj.username.label }}</label> {{ form_obj.username }} </div> <div> <label for="{{ form_obj.password.id_for_label }}">{{ form_obj.password.label }}</label> {{ form_obj.password }} </div> <div> <label for="{{ form_obj.re_password.id_for_label }}">{{ form_obj.re_password.label }}</label> {{ form_obj.re_password }} </div> <input type="button" value="註冊"> </form> </body> </html>
由於這是django自己的表,所以不能像之前用我們自己的表的創建方法去創建用戶,這裏提供了:
create_user():
auth 提供的一個創建新用戶的方法,需要提供必要參數(username、password)等。
def register(request): form_obj = RegForm() if request.method == ‘POST‘: form_obj = RegForm(request.POST) if form_obj.is_valid(): print(form_obj.cleaned_data)#打印form表單中經過驗證的數據 cleaned_data中多了re_password字段。 # 吧re_pqssword字段從cleaned_data移除 form_obj.cleaned_data.pop(‘re_password‘) User.objects.create_user(**form_obj.cleaned_data) return HttpResponse(‘ok‘) return render(request,‘register.html‘,{‘form_obj‘:form_obj})
create_superuser():
auth 提供的一個創建新的超級用戶的方法,需要提供必要參數(username、password)等。
方法和創建普通用戶的方法相同
check_password(password):
auth 提供的一個檢查密碼是否正確的方法,需要提供當前請求用戶的密碼。
密碼正確返回True,否則返回False。
ok = user.check_password(‘舊密碼‘) #user就是當前登陸的user request.user
set_password(password):
auth 提供的一個修改密碼的方法,接收 要設置的新密碼 作為參數。
註意:設置完一定要調用用戶對象的save方法!!!
user.set_password(‘新密碼’) user.save()
一個修改密碼功能的簡單示例:
views.py代碼:
def setpassword(request): err_msg = ‘‘ if request.method == ‘POST‘: # print(request.user) # print(request.user.password) # print(request.user.username) user = request.user old_password = request.POST.get(‘old_password‘) new_password = request.POST.get(‘new_password‘) print(old_password, new_password) if user.check_password(old_password): user.set_password(new_password) user.save() return redirect(‘/login/‘) else: err_msg = ‘原密碼輸入有誤‘ return render(request,‘setpassword.html‘,{‘err_msg‘: err_msg})
html代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>修改密碼</title> </head> <body> <form action="" method="post"> {% csrf_token %} <div> <label for="old_password">原密碼:</label> <input type="text" name="old_password"> </div> <div> <label for="new_password">新密碼:</label> <input type="password" name="new_password"> </div> <input type="submit" value="提交"> <span>{{ err_msg }}</span> </form> </body> </html>
現在我們想要在auth_user表上添加一個字段怎麽辦?
擴展默認的auth_user表:
from django.contrib.auth.models import AbstractUser class UserInfo(AbstractUser): """ 用戶信息表 """ phone = models.CharField(max_length=11, null=True, unique=True)
註意:
按上面的方式擴展了內置的auth_user表之後,一定要在settings.py中告訴Django,我現在使用我新定義的UserInfo表來做用戶認證。寫法如下:
# 引用Django自帶的User表,繼承使用時需要設置
AUTH_USER_MODEL = "app名.UserInfo"
再次註意:
一旦我們指定了新的認證系統所使用的表,我們就需要重新在數據庫中創建該表,而不能繼續使用原來默認的auth_user表了。
django框架之auth模塊