zoukankan      html  css  js  c++  java
  • Django—中间件

    CBV加装饰器(session)

    要在CBV视图中使用我们上面的check_login装饰器,有以下三种方式:

    from django.utils.decorators import method_decorator

    from django.shortcuts import render,redirect,HttpResponse
    from django.views import View
    from django.utils.decorators import method_decorator
    
    # Create your views here.
    def login(request):
        if request.method == 'POST':
            username = request.POST.get('username')
            password = request.POST.get('password')
            if username == 'zyl' and password == '123':
                request.session['name'] = 'zyl'
                return redirect('/home/')
        return render(request,'login.html')
    
    from functools 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
    
    # @method_decorator(login_auth,name='get') 第二种 name参数必须指定
    class MyHome(View):
        @method_decorator(login_auth)    # 第三种  get和post都会被装饰
        def dispatch(self, request, *args, **kwargs):
            super().dispatch(request,*args,**kwargs)
        # @method_decorator(login_auth)  # 第一种
        def get(self,request):
            return HttpResponse('get')
        def post(self,request):
            return  HttpResponse('post')

    urls.py

    url(r'^login/', views.login),
    url(r'^home/', views.MyHome.as_view()),

    中间件

    当Django处理一个Request的过程是首先通过中间件,然后再通过默认的URL方式进行的。我们可以在Middleware这个地方把所有Request拦截住,用我们自己的方式完成处理以后直接返回Response,
    主要用于在全局范围内改变Django的输入和输出

    中间件能干嘛?

    控制用户访问频率,全局登录校验,用户访问白名单,黑名单等

    Django默认的Middleware如下:

    MIDDLEWARE = [
        'django.middleware.security.SecurityMiddleware',
        'django.contrib.sessions.middleware.SessionMiddleware',
        'django.middleware.common.CommonMiddleware',
        'django.middleware.csrf.CsrfViewMiddleware',
        'django.contrib.auth.middleware.AuthenticationMiddleware',
        'django.contrib.messages.middleware.MessageMiddleware',
        'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]

    每一个中间件都有具体的功能。中间件可以定义五个方法。

    1.请求来的时候会依次执行每一个中间件里面的process_request方法(如果没有直接通过)
    2.响应走的时候会依次执行每一个中间件里面的process_response方法(如果没有直接通过)

    分析源码

    from django.middleware.security import SecurityMiddleware

     同样,我们再查看一个:

    from django.middleware.common import CommonMiddleware

    再来

    from django.middleware.csrf import CsrfViewMiddleware

    我们会发现一个相同点,就是都有process_request和process_response,但并不是所有的中间件都有process_request,但是所有的中间件都是由process_response,而且process_response必须要有返回值,process_request没有,如果process_request有返回值的话就不会执行后面的程序了(所以这里可以拦截)

    我们从浏览器发出一个请求Request,得到一个响应后的内容HttpResponse,也就是说,每一个请求都是先通过中间件中的process_request函数,这个函数返回None 或者HttpResponse 对象,如果返回前者,继续处理其他中间件,如果返回前者,继续处理其他中间件,如果返回一个HttpResponse,就处理终止,返回到网页上。

    中间件不用集成任何类(可以继承object),下面一个中间件大概的样子:

    class CommonMiddleware(object):
        def process_request(self, request):
            return None
     
        def process_response(self, request, response):
            return response

    自定义中间件的方法

    中间件一共有五个方法:

    process_request(self, request)
     
    process_view(self, request, callback, callback_args, callback_kwargs)
     
    process_template_response()
     
    process_exception(self, request, exception)
     
    process_response(self, request, response)

    Request预处理函数:process_request(self,request)

      如果返回None,Django继续执行这个request,如果返回的是HttpRsoponse对象,Django不会执行任何除了process_response以外的其他中间件以及相应的view,Django立即返回该HttpResponse

    View预处理函数:process_view(self, request, callback, callback_args, callback_kwargs)

      这个方法的条用实际在Django执行完request预处理函数并确定待执行的view之后,但在view函数实际执行之前

    request:HttpRequest 对象。
     
    callback:Django将调用的处理request的python函数. 这是实际的函数对象本身,
     而不是字符串表述的函数名。
     
    args:将传入view的位置参数列表,但不包括request参数(它通常是传入view的第一个参数)。
     
    kwargs:将传入view的关键字参数字典。

    process_view() 应当返回None或 HttpResponse 对象。如果返回 None, Django将继续处理这个request ,执行后续的中间件, 然后调用相应的view。

    如果返回 HttpResponse 对象,Django 将不再执行任何其它的中间件(不论种类)以及相应的view,Django将立即返回。

    Template模板渲染函数:process_template_response()

      默认不执行,只有在视图函数的返回结果对象中有render方法才会执行,并把对象的render方法的返回值返回给用户(注意不返回视图函数的return的结果了,而是返回视图函数return值(对象)中render方法的结果)

    Exception后处理函数:process_exception(self, request, exception)

    这个方法只有在request处理过程中出了问题并且view函数抛出了一个未捕获的异常才会被调用。这个钩子可以用来发送错误通知,将现场相关信息输出到日志文件,或者甚至尝试从错误中自动恢复。

    Response 后处理函数:process_response(self, request, response)

      这个方法的调用时机在 Django 执行 view 函数并生成 response 之后。

      

    总结:
        需要你掌握的:
        process_request:请求来的时候从上往下依次执行每一个中间件里面的process_request
        process_response :响应走的时候会从下往上依次执行每一个中间件里面的process_response方法
                            
        了解:
        process_view:路由匹配成功执行视图之前自动触发(从上往下依次执行)
        process_exception:当视图函数报错了,自动触发(从下往上依次执行)
        process_template_response:视图函数返回的对象有一个render()方法
                            (或者表明该对象是一个TemplateResponse对象或等价方法)(从下往上依次执行)
            

    自定义中间件方法练习

    process_request 和 process_response方法

      当用户发起请求的时候会依次经过所有的中间件,这个时候的请求是process_request,最后到达views的函数中,views函数处理后,在依次穿过中间件,这个时候是process_response,最后返回给请求者。

      上述截图中的中间件都是django中的,我们也可以自己定义一个中间件,我们可以自己写一个类,但是必须继承MiddlewareMixin。

    需要导入:

    from django.utils.deprecation import MiddlewareMixin

    在 views 中:

    def index(request):
     
        print("view函数...")
        return HttpResponse("OK")

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse
    
    class Md1(MiddlewareMixin):
        def process_request(self,request):
            print('md1请求')
    
        def process_response(self,request,response):
            print('md1返回')
            return response
    
    class Md2(MiddlewareMixin):
        def process_request(self,request):
            print('md2请求')
    
        def process_response(self,request,response):
            print('md2返回')
            return response

     

     1 from django.utils.deprecation import MiddlewareMixin
     2 from django.shortcuts import HttpResponse
     3 
     4 class Md1(MiddlewareMixin):
     5     def process_request(self,request):
     6         print('md1请求')
     7 
     8     def process_response(self,request,response):
     9         print('md1返回')
    10         return response
    11 
    12 class Md2(MiddlewareMixin):
    13     def process_request(self,request):
    14         print('md2请求')
    15         return HttpResponse('M2中断d')
    16     def process_response(self,request,response):
    17         print('md2返回')
    18         return response

    注意:如果当请求到达请求2的时候直接不符合条件返回,即return HTTPResponse(“Md2中断”),程序将请求直接发给中间件2 返回,然后依次返回到请求者

    流程图

    process_view 方法

    from django.utils.deprecation import MiddlewareMixin
    from django.shortcuts import HttpResponse
    
    class Md1(MiddlewareMixin):
        def process_request(self,request):
            print('md1请求')
    
        def process_response(self,request,response):
            print('md1返回')
            return response
    
        def process_view(self,request,callback, callback_args, callback_kwargs):
            print('Md1view')
    
    class Md2(MiddlewareMixin):
        def process_request(self,request):
            print('md2请求')
            # return HttpResponse('M2中断d')
        def process_response(self,request,response):
            print('md2返回')
            return response

    结果

    流程图

    CSRF跨站请求伪造

      我们之前已经接触过一个csrf相关的中间件了?我们一开始让大家把他注释掉,再提交post请求的时候,就不会被forbidden了,后来学会使用csrf_token之后就不再注释这个中间件了。

    简介

    django为用户实现防止跨站请求伪造的功能,通过中间件

    django.middleware.csrf.CsrfViewMiddleware 来完成。而对于django中设置防跨站请求伪造功能有分为全局和局部。

    全局:

      中间件 django.middleware.csrf.CsrfViewMiddleware

    局部:

    • @csrf_protect,为当前函数强制设置防跨站请求伪造功能,即便settings中没有设置全局中间件。
    • @csrf_exempt,取消当前函数防跨站请求伪造功能,即便settings中设置了全局中间件。

    注:from django.views.decorators.csrf import csrf_exempt,csrf_protect

     方式

    $.ajaxSetup({
        data: {csrfmiddlewaretoken: '{{ csrf_token }}' },
    });
    <form action="/index3/" method="post">
    {#    {% csrf_token %}#}
        <p>username:<input type="text" name="username"></p>
        <p>money:<input type="text" name="money"></p>
        <p>others:<input type="text" name="others"></p>
        <input type="submit">
    </form>
    <button>ajax</button>
    <script>
        $('button').click(function () {
            $.ajax({
                url:'',
                type:'post',
                data:{'name':'jason','csrfmiddlewaretoken':$('[name="csrfmiddlewaretoken"]').val()},
                success:function (data) {
                    console.log(data)
                }
            })
        })
    </script>
    from django.views.decorators.csrf import csrf_exempt,csrf_protect
    @csrf_exempt  # 不校验csrf
    def index1(request):
        return HttpResponse('ok')
    
    @csrf_protect  # 校验csrf
    def index2(request):
        return HttpResponse('ok')

    csrf装饰CBV

    from django.utils.decorators import method_decorator
    
    # @method_decorator(csrf_exempt,name='post')  # 不行  不能给单独某一个视图函数加
    @method_decorator(csrf_exempt,name='dispatch')  # 可以
    class Index3(View):
        # @method_decorator(csrf_exempt)   # 第三种  可以
        def dispatch(self, request, *args, **kwargs):
            super().dispatch(request,*args,**kwargs)
    
        def get(self,request):
            return HttpResponse('get')
    
        # @method_decorator(csrf_exempt)  # 不行
        def post(self,request):
            return HttpResponse('post')

    csrf装饰CBV需要注意(******)
    csrf_protect 跟正常的CBV装饰器一样 三种
    csrf_exempt 只能有下面两种方式
    @method_decorator(csrf_exempt,name='dispatch') # 第一种
    class Index3(View):
    # @method_decorator(csrf_exempt) # 第二种
    def dispatch(self, request, *args, **kwargs):
    super().dispatch(request,*args,**kwargs)
    其实都是给dispatch加

  • 相关阅读:
    张旭升20162329 2006-2007-2 《Java程序设计》第一周学习总结
    预备作业03——20162329张旭升
    预备作业02 : 体会做中学-20162329 张旭升
    预备作业01——20162329
    FPGA的软核与硬核
    网页调用vlc并播放网络视频
    vue视频插件VLC
    vue+vue-video-player实现弹窗播放视频
    【面向对象程序设计】作业三
    【面向对象程序设计】作业二
  • 原文地址:https://www.cnblogs.com/zhengyuli/p/11047907.html
Copyright © 2011-2022 走看看