# 写一个装饰器验证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'
最后补一张请求流程图