一、csrf跨站請(qǐng)求的相關(guān)裝飾器
'''
django.middleware.csrf.CsrfViewMiddlewareDjango中有一個(gè)中間件對(duì)csrf跨站做了驗(yàn)證,我只要把csrf的這個(gè)中間件打開,
那就意味著所有的方法都要被驗(yàn)證
'''在所有的視圖函數(shù)中:只有幾個(gè)視圖函數(shù)做驗(yàn)證只有幾個(gè)函數(shù)不做驗(yàn)證csrf_protect: 哪個(gè)視圖函數(shù)加了這個(gè)裝飾器,這個(gè)函數(shù)就會(huì)做驗(yàn)證
csrf_exempt:哪個(gè)視圖函數(shù)加了這個(gè)裝飾器,這個(gè)函數(shù)就不會(huì)做驗(yàn)證
-------------------------------------------------------------------------------
注意:加入裝飾器驗(yàn)證csrf,先導(dǎo)入下面這行代碼:
from django.views.decorators.csrf import csrf_exempt,csrf_protect一、FBV模式下:
情境1:1.先在settings.py配置文件中注釋下面這行代碼:2.然后在需要驗(yàn)證的視圖函數(shù)上面加上 @csrf_protect 則說明這個(gè)視圖函數(shù)需要經(jīng)過驗(yàn)證.@csrf_protectdef index(request):return render(request, 'index.html')def func(request):return render(request, 'func.html')3. 上述兩個(gè)視圖函數(shù)中,由于index函數(shù)加了裝飾器csrf_protect所以需要經(jīng)過csrf驗(yàn)證,而func函數(shù)不需要情境2:1.先打開settings.py配置文件中下面這行代碼:即不用注釋'django.middleware.csrf.CsrfViewMiddleware',2.然后在不需要驗(yàn)證的視圖函數(shù)上面加上 @csrf_exempt 則說明這個(gè)視圖函數(shù)不需要經(jīng)過驗(yàn)證,而沒有加任何裝飾的視圖函數(shù)必須經(jīng)過csrf驗(yàn)證@csrf_exemptdef index(request):return render(request, 'index.html')def func(request):return render(request, 'func.html')return render(request, 'func.html')3. 上述兩個(gè)視圖函數(shù)中,在'django.middleware.csrf.CsrfViewMiddleware',沒有被注釋的情況下:由于index函數(shù)加了裝飾器csrf_exempt,所以不需要經(jīng)過csrf驗(yàn)證,而func函數(shù)需要csrf驗(yàn)證。情境3:1.在打開settings.py配置文件中下面這行代碼的情況下:'django.middleware.csrf.CsrfViewMiddleware',2.然后在不需要驗(yàn)證的視圖函數(shù)上面加上 @csrf_exempt 則說明這個(gè)視圖函數(shù)不需要經(jīng)過驗(yàn)證,而另一個(gè)加了裝飾器 csrf_protect 的視圖函數(shù)也必須經(jīng)過csrf驗(yàn)證@csrf_exemptdef index(request):return render(request, 'index.html')@csrf_protectdef func(request):return render(request, 'func.html')3. 上述兩個(gè)視圖函數(shù)中,由于index函數(shù)加了裝飾器csrf_exempt所以不需要經(jīng)過csrf驗(yàn)證,而func函數(shù)加了裝飾器csrf_protect需要csrf驗(yàn)證。二、CBV模式下:
注意:加入裝飾器,先導(dǎo)入下面代碼:
from django.views.decorators.csrf import csrf_exempt,csrf_protect
from django.views import View
from django.utils.decorators import method_decorator方式1:在post函數(shù)上,加入csrf_exempt無效,還是報(bào)錯(cuò):Forbidden (403)1.先打開settings.py配置文件中下面這行代碼:即不用注釋'django.middleware.csrf.CsrfViewMiddleware',2.然后在不需要驗(yàn)證的視圖函數(shù)上面加上 @csrf_exempt 則說明這個(gè)視圖函數(shù)不需要經(jīng)過驗(yàn)證,但是結(jié)果是還需要驗(yàn)證,說明此方式無效。class Login(View):@method_decorator(csrf_exempt)def post(self, request):print('post')return HttpResponse('post')方式2:在類的投訴,加入csrf_exempt無效,還是報(bào)錯(cuò):Forbidden (403)1.先打開settings.py配置文件中下面這行代碼:即不用注釋'django.middleware.csrf.CsrfViewMiddleware',2.在類的頭上加了裝飾器,但是還是無效@method_decorator(csrf_exempt, name='post')class Login(View):def post(self, request):print('post')return HttpResponse('post')方式3:CBV的驗(yàn)證只有在dispatch函數(shù)上加裝飾器,需要驗(yàn)證的函數(shù)才能通過驗(yàn)證class Login(View):@method_decorator(csrf_exempt)def dispatch(self, request, *args, **kwargs):return super(Login, self).dispatch(request, *args, **kwargs)def post(self, request):print('post')return HttpResponse('post')注意:在settings.py配置文件中注釋下面這行代碼:然后,對(duì)三種方式進(jìn)行驗(yàn)證csrf_protect,都可以CBV針對(duì)于csrf_exempt:只有第三張方式才生效,其余兩種方式不行
CBV針對(duì)于csrf_protect:三種方式都可以
class Login(View):@method_decorator(csrf_protect) def dispatch(self, request, *args, **kwargs):return super().dispatch(request, *args, **kwargs)def post(self, request):print("post")return HttpResponse("post")
二、Auth模塊的使用
Auth模塊是什么?Auth模塊是Django自帶的用戶認(rèn)證模塊:我們?cè)陂_發(fā)一個(gè)網(wǎng)站的時(shí)候,無可避免的需要設(shè)計(jì)實(shí)現(xiàn)網(wǎng)站的用戶系統(tǒng)。此時(shí)我們需要實(shí)現(xiàn)包括用戶注冊(cè)、用戶登錄、用戶認(rèn)證、注銷、修改密碼等功能,這還真是個(gè)麻煩的事情呢。Django作為一個(gè)完美主義者的終極框架,當(dāng)然也會(huì)想到用戶的這些痛點(diǎn)。它內(nèi)置了強(qiáng)大的用戶認(rèn)證系統(tǒng)–auth,它默認(rèn)使用 auth_user 表來存儲(chǔ)用戶數(shù)據(jù)。注意事項(xiàng):在執(zhí)行數(shù)據(jù)庫遷移命令的時(shí)候,會(huì)自動(dòng)生成一個(gè)默認(rèn)的表,其中有auth_開頭的很多表auth_user表的作用:djagno自帶的后臺(tái)管理系統(tǒng)所依賴的數(shù)據(jù)就在這張表中默認(rèn)情況下,auth_user表是空表,沒有用戶名和密碼,因此我們需要自己創(chuàng)建用戶數(shù)據(jù)需要?jiǎng)?chuàng)建一個(gè)超級(jí)管理員賬號(hào)才能登錄'''
創(chuàng)建超級(jí)管理員命令:python manage.py createsuperuser在配置文件settings.py中修改語言為中文和時(shí)區(qū):
# 語言
LANGUAGE_CODE = 'zh-hans'
# 時(shí)區(qū)
TIME_ZONE = 'Asia/Shanghai'
USE_I18N = True
USE_L10N = True
USE_TZ = False'''
三、Auth模塊的相關(guān)方法
登錄功能、注冊(cè)功能、修改密碼、退出系統(tǒng)、認(rèn)證功能等學(xué)習(xí)如何使用
'''當(dāng)局部和全局都存在的時(shí)候,按局部的如果局部沒有,按照全局的
'''
@login_required(login_url='/order/login/')
def order(request):passLOGIN_URL = '/login/' '''
如果沒有登錄則 跳轉(zhuǎn)到 http://127.0.0.1:8000/accounts/login/?next=/order/
但是若加了裝飾器,則跳轉(zhuǎn)到指定的路由頁面在settings.py配置文件中全局配置,
LOGIN_URL = '/login/'當(dāng)局部和全局都在的時(shí)候,按局部的,若局部沒有,則按全局的
'''
@login_required(login_url='/login/')
def order(request):print(request.user.is_authenticated) return HttpResponse('order')def order1(request):return HttpResponse('order')---------------------------------------------------------------------------------------auth模塊的后端登錄代碼:
from django.contrib import authdef login(request):if request.method == 'POST':username = request.POST.get('username')password = request.POST.get('password')'''這里的登錄,我們使用auth模塊,登錄的時(shí)候所使用的表是auth_user表'''user_obj = auth.authenticate(request, username=username, password=password) '''返回值是登錄成功之后的用戶對(duì)象'''print(user_obj) print(user_obj.username) print(user_obj.password) '''注意事項(xiàng)1:傳遞參數(shù)的時(shí)候,用戶名和密碼必須同時(shí)傳入''''''注意事項(xiàng)2:由于上面使用了auth模塊,在此不建議這樣寫,auth模塊都提供有相應(yīng)的方法要么全部使用auth模塊的方法,要么全部自己寫,不建議混合使用'''auth.login(request, user_obj)'''只要寫了auth.login,那么就可以在全局有任何request的地方使用request.user拿到用戶對(duì)象'''return redirect('/home/')return render(request, '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><style>body {{#background: url('https://pic2.zhimg.com/3ae866e7992a94069c7e0c417aac807d_r.jpg') no-repeat;#}background: url('https://img0.baidu.com/it/u=741268616,1401664941&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1691859600&t=5c5bee3052ecec363c1ecc2eea9ac3f7') no-repeat;background-size: 100% 130%;}#login_box {width: 20%;height: 400px;background-color: #00000060;margin: auto;margin-top: 10%;text-align: center;border-radius: 10px;padding: 50px 50px;}h2 {color: #ffffff90;margin-top: 5%;}#input-box {margin-top: 5%;}span {color: #fff;}input {border: 0;width: 60%;font-size: 15px;color: #fff;background: transparent;border-bottom: 2px solid #fff;padding: 5px 10px;outline: none;margin-top: 10px;}button {margin-top: 50px;width: 60%;height: 30px;border-radius: 10px;border: 0;color: #fff;text-align: center;line-height: 30px;font-size: 15px;background-image: linear-gradient(to right, #30cfd0, #330867);}#sign_up {margin-top: 45%;margin-left: 60%;}a {color: #b94648;}</style>
</head><body>
<div id="login_box"><h2>登錄頁面</h2><form action="" method="post"><div id="input_box"><input type="text" placeholder="請(qǐng)輸入用戶名" name="username"></div><div class="input_box"><input type="password" placeholder="請(qǐng)輸入密碼" name="password"></div><button>提交</button>
{# <input type="submit" value="提交">#}<br></form>
</div>
</body>
</html>
四、Auth模塊之退出系統(tǒng)
def logout(request):auth.logout(request)return redirect('/home/')
六、Auth模塊之修改密碼功能
1.驗(yàn)證老密碼是否正確
is_right = request.user.check_password(old_password)2.修改密碼
request.user.set_password(new_password)
request.user.save() 案例代碼:
@login_required
def set_password(request):if request.method == 'POST':old_password = request.POST.get('old_password')new_password = request.POST.get('new_password')re_password = request.POST.get('re_password')if new_password == re_password:is_right = request.user.check_password(old_password)if is_right:request.user.set_password(new_password)request.user.save()return redirect('/home/')return render(request, 'set_password.html', locals())前端代碼:
<div id="login_box"><h2>修改密碼</h2><form action="" method="post">{% csrf_token %}<div id="input_box">用戶名:<input type="text" name="username" readonly value="{{ request.user.username }}"></div><div class="input_box">舊密碼:<input type="password" placeholder="請(qǐng)輸入舊密碼" name="old_password"></div><div class="input_box">新密碼:<input type="password" placeholder="請(qǐng)輸入新密碼" name="new_password"></div><div class="input_box">請(qǐng)確認(rèn):<input type="password" placeholder="確認(rèn)新密碼" name="re_password"></div><button>提交</button>
{<br></form>
</div>
七、Auth模塊之注冊(cè)功能
'''
入庫的三種方式:方式1:自動(dòng)入庫到auth_user表,但是密碼是明文密碼,登錄的時(shí)候是經(jīng)過加密處理的,則登錄不上User.objects.create(username=username, password=password)方式2:密碼是密文入庫User.objects.create_user(username=username, password=password)方式3:創(chuàng)建超級(jí)用戶,并且密碼是密文存入,但是必須指定郵箱,否則報(bào)錯(cuò)User.objects.create_superuser(username=username, password=password, email='123@qq.com')
'''from django.contrib.auth.models import Userdef register(request):if request.method == 'POST':username = request.POST.get('username')password = request.POST.get('password')User.objects.create_superuser(username=username, password=password, email='123@qq.com')return redirect('/login/')return render(request, 'register.html')
八、擴(kuò)展默認(rèn)的auth_user表
默認(rèn)情況下使用的就是auth_user的默認(rèn)字段
擴(kuò)展我們自己的字段前提是:所有的模型類都繼承
from django.contrib.auth.models import AbstractUser現(xiàn)在是要在auth_user表的基礎(chǔ)上擴(kuò)展字段,不要繼承了models.Model**************************************************************************
注意:擴(kuò)展之后需要在配置文件(settings.py)中加一句話AUTH_USER_MODEL = '應(yīng)用名.表名'eg:AUTH_USER_MODEL = 'app01.UserInfo'-------------------------------------------------------------------------------------注意:"""在擴(kuò)展表之前數(shù)據(jù)庫不能夠遷移,擴(kuò)展這個(gè)表需要在遷移數(shù)據(jù)庫之前做"""問:如果你遷移了,還想擴(kuò)展怎么辦?1. 換庫2. 需要?jiǎng)h除很多個(gè)應(yīng)用的migrations文件夾
注意:遷移報(bào)錯(cuò)的時(shí)候,有可能會(huì)用到下面這句代碼:python manage.py migrate myapp --fake---------------重點(diǎn):擴(kuò)展表之后發(fā)生的變化-------------------
"""擴(kuò)展表之后發(fā)生的變化:1. 原來的auth_user表不存在了,換成你自己新建的表名了2. 原來的auth_user表中的字段還都在,然后多了自己擴(kuò)展的字段3. 繼承的類要發(fā)生改變AbstractUser4. 在配置文件中加入下面一句話:AUTH_USER_MODEL = 'app01.UserInfo'AUTH_USER_MODEL = '應(yīng)用名.類名'5. 擴(kuò)展之后還是按照原來的auth_user表使用6. auth模塊中的數(shù)據(jù)還是你擴(kuò)展的表7. 擴(kuò)展之前別遷移.
"""--------------------------------------------------------------------
案例:
因?yàn)橹斑w移過了,所以我選擇換庫:從sqlite3---->mysql1.在settings.py配置文件中把數(shù)據(jù)庫換成MySQL:
'default': {'ENGINE': 'django.db.backends.mysql','NAME': 'db22','HOST': '127.0.0.1','PORT': 3306,'USER': 'root','PASSWORD': 'root','CHARSET': 'utf8'},
2.擴(kuò)展表的字段:先導(dǎo)入AbstractUser,讓擴(kuò)展表繼承AbstractUser
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):phone = models.CharField(max_length=64)avatar = models.CharField(max_length=64)
3.遷移
python manage.py makemigrations
python manage.py migrate