# 寫一個裝飾器驗證session from functions import wraps def login_auth(func) @wraps(func) def inner(request,*args,**kwargs) if request.session.get('name') return func(request,*args,**kwargs) return redirect('/login/') return inner
from django.views import View from django.utils.decorators import method_decorator class MyHome(View): def dispatch(self,request,*args,**kwargs) super().dispatch(reauest,*args,**kwargs) @method_decorator(login_auth) def get(self,request): return HttpResponse('ok')
from django.views import View from django.utils.decorators import method_decorator @method_decorator(login_auth,name='get') # name參數必須指定 class MyHome(View): def dispatch(self,request,*args,**kwargs) super().dispatch(reauest,*args,**kwargs) def get(self,request): return HttpResponse('ok')
from django.views import View from django.utils.decorators import method_decorator class MyHome(View): @method_decorator(login_auth) # get和post都會被裝飾 def dispatch(self,request,*args,**kwargs) super().dispatch(reauest,*args,**kwargs) def get(self,request): return HttpResponse('ok')
中間件用於在全局範圍內改變Django的輸入和輸出,須要謹慎使用,使用不當會影響性能html
簡單來講就是在視圖函數執行以前和執行以後均可以作一些額外的操做,能夠用來控制用戶訪問頻率,全局登陸校驗,用戶訪問白名單,黑名單等python
以上方法的返回值能夠是None或一個HTTPResponse對象,若是是None,則繼續按照django定義的規則向後繼續執行,若是是HTTPResponse對象,則直接將該對象返回給用戶ajax
在應用下新建一個文件夾,在文件夾下新建一個py文件,而後在settings配置文件中註冊django
須要一個參數request,能夠對request對象進行一系列的操做,後續也能夠在視圖函數中經過相同的方式獲取值後端
1.中間件的process_request方法是在執行視圖函數以前執行的 2.當配置多箇中間件時,會按照MIDDLEWARE中的註冊順序,也就是列表的索引值,從前到後依次執行的 3.不一樣中間件之間傳遞的request都是同一個對象
須要兩個形參,request和response,response是視圖函數返回的HTTPResponse對象(django後臺處理後給出的一個具體的視圖)瀏覽器
1.中間件的process_response方法是在視圖函數以後執行的 2.當配置多箇中間件時,會按照MIDDLEWARE的註冊順序倒序執行的 3.不一樣中間件之間傳遞的request都是同一個對象
須要四個參數:session
1.diango會在路由系統以後,視圖函數以前調用process_view方法 2.按照MIDDLEWARE中的註冊順序從前日後順序執行
須要兩個參數:app
1.中間件的process_exception方法是在視圖函數以後執行的 2.當配置多箇中間件時,會按照MIDDLEWARE的註冊順序倒序執行的
若是視圖函數中無異常,該方法不執行函數
須要兩個參數:工具
在視圖函數執行完後當即執行,順序是倒序,可是有一個條件,那就是視圖函數返回的對象有一個render()方法
請求到達中間件以後,先按照正序執行每一個註冊中間件的process_request方法,process_request方法返回的值是None,就依次執行,若是返回的值是HttpResponse對象,再也不執行後面的process_request方法,而是執行當前對應中間件的process_response方法(注意不是掉頭執行全部的process_response方法),將HttpResponse對象返回給瀏覽器。也就是說:若是MIDDLEWARE中註冊了6箇中間件,執行過程當中,第3箇中間件返回了一個HttpResponse對象,那麼第4,5,6中間件的process_request和process_response方法都不執行,順序執行3,2,1中間件的process_response方法。
process_request方法都執行完後,匹配路由,找到要執行的視圖函數,先不執行視圖函數,先執行中間件中的process_view方法,process_view方法返回None,繼續按順序執行,全部process_view方法執行完後執行視圖函數。假如中間件3 的process_view方法返回了HttpResponse對象,則4,5,6的process_view以及視圖函數都不執行,直接從最後一箇中間件,也就是中間件6的process_response方法開始倒序執行。
process_template_response和process_exception兩個方法的觸發是有條件的,執行順序也是倒序
<form method='post'> {% csrf_token %} </form>
將隨機產生的字符串放進數據傳給後端,鍵固定,值以屬性查找的方式找到
{% csrf_token %} <button> ajax </button> <script> $('button').click(function){ $.ajax({ url:'', type:'post', data:{'name':'lucas','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()}, //第一種 data:{'name':'lucas','csrfmiddlewaretoken':'{{ csrf_token }}'}, //第二種 success:function(data){ console.log(data) } }) } </script>
# 只想給某個視圖函數加上csrf校驗 from django.views.decorators.csrf import csrf_exempt,csrf_protect # 局部禁用 @csrf_exempt def index(request): pass # 局部使用 @csrf_procept def login(request): pass # CBV比較特殊,不能單獨加在某個方法上 # 只能加在類上或dispatch方法上 from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt,csrf_protect @method_decorator(csrf_exempt,name='dispatch') # 第一種 class Csrf_Token(View): @method_decorator(csrf_exempt) # 第二種 def dispatch(self,request,*args,**kwargs): res = super().dispatch(request,*args,**kwargs) return res @method_decorator(csrf_exempt) # 這裏這麼寫不行!!! def get(self,request): pass def post(self,request): pass
注意:csrf_protect 跟正常的CBV裝飾器同樣 三種
from django.contrib import auth def login(request): if request.method == 'POST': name = request.POST.get('name') pwd = request.POST.get('pwd') user = auth.authenticate(request,username=name,password=pwd) # 判斷用戶是否存在 if user: return redirect('/home/') return render(request,'login.html')
if user: auth.login(request,user) # 一旦記錄了,能夠在任意地方經過request.user獲取當前登入對象
def index(request): print(request.user.is_authenticated()) # 判斷當前用戶是否已經登入 print(request.user,type(request.user)) # 獲取當前登入用戶對象
def logout(request): auth.logout(request) # request.session.flush
def auth_register(request): if request.method == 'POST': username = request.POST.get('username') password = request.POST.get('password') user_obj = auth.authenticate(request,username=username) if user_obj: return HttpResponse('當前用戶已存在') # models.User.objects.create(username=username,password=password) # User.objects.create(username=username,password=password) # 不能再用create建立 # User.objects.create_user(username=username,password=password) # 建立普通用戶 User.objects.create_superuser(username=username,password=password,email='123@163.com') # 建立超級用戶 return render(request,'auth_register.html')
def auth_password(request): print(request.user.password) is_res = request.user.check_password('jason123') # 校驗密碼是否一致 if is_res: request.user.set_password('666') # 設置新密碼 request.user.save() # 修改密碼必須save保存 否則無效 return HttpResponse('ok')
局部配置
from django.contrib.auth.decorators import login_required @login_required(login_url='/login/') def home(request): return HttpResponse('ok')
自定義登入的URL
須要在settings文件中修改
# auth自動跳轉 LOGIN_URL = '/login/' # 這裏配置項目登入頁面的路由,原路徑仍是要本身判斷
經過繼承內置的AbstractUser類,來定義一個本身的Model類
既能根據項目需求靈活的設計用戶表,又能使用Django強大的認證系統
from django.db import models from django.contrib.auth.models import User,AbstractUser # Create your models here. # 第一種擴展字段的方式(瞭解便可) # class Userinfo(models.Model): # phone = models.CharField(max_length=32) # avatar = models.CharField(max_length=32) # ab = models.OneToOneField(to=User) class Userinfo(AbstractUser): phone = models.CharField(max_length=32) avatar = models.CharField(max_length=32)
注意:擴展了內置的auth_user表以後,必定要在settings中告訴Django
# AUTH_USER_MODEL = 'app名.models裏面對應的模型表名' AUTH_USER_MODEL = 'app01.Userinfo'
最後補一張請求流程圖