Django补充——中间件请求的生命周期等

Posted Wang-Vee

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django补充——中间件请求的生命周期等相关的知识,希望对你有一定的参考价值。

一:中间件

django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法。

在django项目的settings模块中,有一个 MIDDLEWARE_CLASSES 变量,其中每一个元素就是一个中间件,如下图。

与mange.py在同一目录下的文件夹 wupeiqi/middleware下的auth.py文件中的Authentication类

中间件中可以定义四个方法,分别是:

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

以上方法的返回值可以是None和HttpResonse对象,如果是None,则继续按照django定义的规则向下执行,如果是HttpResonse对象,则直接将该对象返回给用户。

 

自定义中间件:

1、创建中间件类

class RequestExeute(object):
      
    def process_request(self,request):
        pass
    def process_view(self, request, callback, callback_args, callback_kwargs):
        i =1
        pass
    def process_exception(self, request, exception):
        pass
      
    def process_response(self, request, response):
        return response
"""
class M1(MiddlewareMixin):

    def process_request(self,request):
        print(\'m1.process_request\')

    def process_view(self,request, view_func, view_func_args, view_func_kwargs):
        print(\'m1.process_view\')

    def process_exception(self,request,exception):
        print(\'m1.process_exception\')

    def process_response(self,request,response):
        print(\'m1.process_response\')
        return response

    def process_template_response(self,request,response):
        print(\'m1.process_template_response\')
        return response

class M2(MiddlewareMixin):
    def process_request(self, request):
        print(\'m2.process_request\')

    def process_view(self, request, view_func, view_func_args, view_func_kwargs):
        print(\'M2.process_view\')

    def process_exception(self,request,exception):
        print(\'m2.process_exception\')
        return HttpResponse(\'开发的程序员已经被打死\')
    def process_response(self, request, response):
        print(\'m2.process_response\')
        return response

    def process_template_response(self,request,response):
        print(\'m2.process_template_response\')
        return response
"""
from django.shortcuts import HttpResponse,redirect
class MiddlewareMixin(object):
    def __init__(self, get_response=None):
        self.get_response = get_response
        super(MiddlewareMixin, self).__init__()

    def __call__(self, request):
        response = None
        if hasattr(self, \'process_request\'):
            response = self.process_request(request)
        if not response:
            response = self.get_response(request)
        if hasattr(self, \'process_response\'):
            response = self.process_response(request, response)
        return response

class M1(MiddlewareMixin):

    def process_response(self, request, response):
        print(\'m2.process_response\')
        return response


class M2(MiddlewareMixin):
    def process_request(self, request):
        print(\'m2.process_request\')
两种方式

2、注册中间件

MIDDLEWARE_CLASSES = (
    \'django.contrib.sessions.middleware.SessionMiddleware\',
    \'django.middleware.common.CommonMiddleware\',
    \'django.middleware.csrf.CsrfViewMiddleware\',
    \'django.contrib.auth.middleware.AuthenticationMiddleware\',
    \'django.contrib.auth.middleware.SessionAuthenticationMiddleware\',
    \'django.contrib.messages.middleware.MessageMiddleware\',
    \'django.middleware.clickjacking.XFrameOptionsMiddleware\',
    \'wupeiqi.middleware.auth.RequestExeute\', #在合适的位置引入
   \'md.middleware.M1\',
   \'md.middleware.M2\',
)

二、 Http请求本质

  Django程序:socket服务端

    a. 服务端监听IP和端口
    c. 接受请求
      \\r\\n\\r\\n:请求头和请求体
      \\r\\n
      &
      request.POST
      request.GET
    d. 响应:
      响应头: location:www.oldboyedu.com
      响应体
    e. 断开连接

  浏览器: socket客户端

    b. 浏览器发送:
      GET请求:
        "GET /index.html http1.1\\r\\nUser-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x6..\\r\\n\\r\\nAccept-Encoding:gzip\\r\\n\\r\\n"
      POST请求:
        "POST /index.html http1.1\\r\\nUser-Agent:Mozilla/5.0 (Windows NT 6.1; Win64; x6..\\r\\n\\r\\nAccept-Encoding:gzip\\r\\n\\r\\nuser=cqz&hobby=lihao"

    e. 断开连接

  COOKIE: 请求头和响应头中存在

三、Django请求的生命周期

wsgi    -> 中间件     -> 路由系统     -> 视图函数(ORM,Template,渲染)
  - wsgiref
  - uwsgi

四、FBV和CBV

1、FBV

FBV(function base views) 就是在视图里使用函数处理请求。

看代码:

urls.py

from django.conf.urls import url, include
# from django.contrib import admin
from mytest import views
 
urlpatterns = [
    # url(r‘^admin/‘, admin.site.urls),
    url(r‘^index/‘, views.index),
]

views.py

from django.shortcuts import render
 
 
def index(req):
    if req.method == ‘POST‘:
        print(‘method is :‘ + req.method)
    elif req.method == ‘GET‘:
        print(‘method is :‘ + req.method)
    return render(req, ‘index.html‘)

注意此处定义的是函数【def index(req):】

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>index</title>
</head>
<body>
    <form action="" method="post">
        <input type="text" name="A" />
        <input type="submit" name="b" value="提交" />
    </form>
</body>
</html>

2、CBV

CBV(class base views) 就是在视图里使用类处理请求。

将上述代码中的urls.py 修改为如下:

from mytest import views
 
urlpatterns = [
    # url(r‘^index/‘, views.index),
    url(r‘^index/‘, views.Index.as_view()),
]

注:url(r‘^index/‘, views.Index.as_view()),  是固定用法。

将上述代码中的views.py 修改为如下:

from django.views import View
 
 
class Index(View):
    def get(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)
 
    def post(self, req):
        print(‘method is :‘ + req.method)
        return render(req, ‘index.html‘)

3、装饰器的使用

from django.utils.decorators import method_decorator

3.1 在get,post方法上

class LoginView(View):
    
    def dispatch(self, request, *args, **kwargs):
        return super(LoginView,self).dispatch(request, *args, **kwargs)

    def get(self,request):
        return render(request,\'login.html\')

    @method_decorator(test)
    def post(self,request):
        # request.GET
        # request.POST # 请求头中的:content-type
        # request.body
        user = request.POST.get(\'user\')
        pwd = request.POST.get(\'pwd\')
        if user == \'alex\' and pwd == "alex3714":
            # 生成随机字符串
            # 写浏览器cookie: session_id: 随机字符串
            # 写到服务端session:
            # {
            #     "随机字符串": {\'user_info\':\'alex}
            # }
            request.session[\'user_info\'] = "alex"
            return redirect(\'/index.html\')
        return render(request, \'login.html\')

3.2 在dispatch方法上

class LoginView(View):
@method_decorator(test)
def dispatch(self, request, *args, **kwargs):
    return super(LoginView,self).dispatch(request, *args, **kwargs)

def get(self,request):
    return render(request,\'login.html\')


def post(self,request):
    # request.GET
    # request.POST # 请求头中的:content-type
    # request.body
    user = request.POST.get(\'user\')
    pwd = request.POST.get(\'pwd\')
    if user == \'alex\' and pwd == "alex3714":
        # 生成随机字符串
        # 写浏览器cookie: session_id: 随机字符串
        # 写到服务端session:
        # {
        #     "随机字符串": {\'user_info\':\'alex}
        # }
        request.session[\'user_info\'] = "alex"
        return redirect(\'/index.html\')
    return render(request, \'login.html\')
View Code

3.3 在类上

@method_decorator(test,name=\'get\')
class LoginView(View):
    
    def dispatch(self, request, *args, **kwargs):
        return super(LoginView,self).dispatch(request, *args, **kwargs)

    def get(self,request):
        return render(request,\'login.html\')


    def post(self,request):
        # request.GET
        # request.POST # 请求头中的:content-type
        # request.body
        user = request.POST.get(\'user\')
        pwd = request.POST.get(\'pwd\')
        if user == \'alex\' and pwd == "alex3714":
            # 生成随机字符串
            # 写浏览器cookie: session_id: 随机字符串
            # 写到服务端session:
            # {
            #     "随机字符串": {\'user_info\':\'alex}
            # }
            request.session[\'user_info\'] = "alex"
            return redirect(\'/index.html\')
        return render(request, \'login.html\')

特殊:CSRF Token只能加到dispatch

from django.views.decorators.csrf import csrf_exempt,csrf_protect
class LoginView(View):
    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        return super(LoginView,self).dispatch(request, *args, **kwargs)

    def get(self,request):
        return render(request,\'login.html\')


    def post(self,request):
        # request.GET
        # request.POST # 请求头中的:content-type
        # request.body
        user = request.POST.get(\'user\')
        pwd = request.POST.get(\'pwd\')
        if user == \'alex\' and pwd == "alex3714":
            # 生成随机字符串
            # 写浏览器cookie: session_id: 随机字符串
            # 写到服务端session:
            # {
            #     "随机字符串": {\'user_info\':\'alex}
            # }
            request.session[\'user_info\'] = "alex"
            return redirect(\'/index.html\')
        return render(request, \'login.html\')
View Code

 

以上是关于Django补充——中间件请求的生命周期等的主要内容,如果未能解决你的问题,请参考以下文章

Django框架请求生命周期

Django请求生命周期

面试-Django框架请求生命周期

Django框架进阶7 django请求生命周期流程图, django中间件, csrf跨站请求伪造, auth认证模块

关于django一个请求的生命周期

Django的请求生命周期与中间件中的5中方法