11.Django -- 中间件

Django -- 中间件

1.django请求生命周期

1.浏览器发过来请求,后台通过wsgi.py中封装的socket模块接收了请求,并且按照http协议进行解包-->封装成request对象
2.把request对象交给中间件,从上到下依次通过每个中间件
3.中间件处理完后交给url控制器进行路径分发,找到对应的视图函数views 
4.视图函数进行orm数据操作和模板渲染等操作,之后return响应内容
5.响应内容倒序(从下到上)通过中间件,交给wsgi.py,通过http协议封装响应socket数据
6.最后把数据再交给浏览器

2.简介

中间件:是介于request(请求)与response(响应)处理之间的一道处理过程,相对比较轻量级,并且在全局上改变django的输入与输出。

应用方向: 限流(限制访问频率),登录认证、权限认证、白名单控制等等

settings.py中的 MIDDLEWARE

# django提供的对所有请求和响应做一些统一处理的时候使用的
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
]

3.自定义中间件

登录认证中间件

1 在应用中创建一个py文件,名字随意 比如: mymiddleware.py
2 在py文件中写上如下内容(基于session登陆认证中间件)
	
  from django.utils.deprecation import MiddlewareMixin
# Django提供的基础中间件类MiddlewareMixin,自定义中间件必须引入
  from django.shortcuts import redirect
    
# 自定义类-->对所有请求进行一个统一的登录认证判断
  class SessionLoginAuth(MiddlewareMixin): #自定义类继承MiddlewareMixin
      
      # 登录认证白名单
      white_list = ['/login/', ]

      def process_request(self, request): 
          #调用父类方法,对所有请求进行处理,自动触发进行

          # 当前请求路径在白名单里面的就放行
          current_path = request.path #获取当前请求路径
          if current_path in self.white_list: 
              return None

          is_login = request.session.get('is_login') #获取session值: True,None
          if not is_login:
              # 如果没有登录,那么直接跳转登录页面去登陆
              return redirect('login')

          # else:
          #     return None  # return None就正常通过这个方法了,方法和函数return值不写,默认return None


3 将自己写的中间件类,配置到settings.py文件中的MIDDLEWARE配置列表中,才能生效

  MIDDLEWARE = [ #添加路径
    'django.middleware.security.SecurityMiddleware',
   
    'app01.mymiddleware.SessionLoginAuth',  # 配置自定义中间件

]

视图:views.py

def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')

    else:
        print(request.POST)
        uname = request.POST.get('username')
        pwd = request.POST.get('password')
        if uname == 'root' and pwd == '123':
            ret = redirect('home')

            # 设置session
            request.session['is_login'] = True
            request.session['uname'] = uname
            '''
                1 生成随机字符串asdf,放到cookie中(sessionid:asdf)
                2 在数据库表(django-session,先进行数据库同步指令)中,
                    data = 序列化然后加密is_login和uname数据
                    session_key  session_data session_expire
                    asdf         data          默认两周

            '''
            return ret
        else:
            return redirect('login')


def person(request):
    return render(request, 'person.html')

def home(request):
    return render(request, 'home.html')

# 退出登陆
def logout(request):
    request.session.flush()  # 退出登录:删除cookie,删除session数据
    return redirect('login')

路由:urls.py

from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^login/', views.login, name='login'),
    url(r'^home/', views.home,name='home'),
    url(r'^person/', views.person,name='person'),
    url(r'^logout/', views.logout,name='logout'),
]

templates目录下HTML文件

login.html

<body>
<form action="" method="post">
    {% csrf_token %}
    用户名: <input type="text" name="username">
    密码: <input type="password" name="password">
    <input type="submit">
</form>
</body>

home.html

<body>
<h1>这是首页</h1>
<a href="{% url 'person' %}">个人中心</a>
</body>

person.html

<body>
<h1>这是个人中心页面</h1>
<a href="{% url 'logout' %}">注销</a>
</body>

4.中间件的执行流程和5个方法

# 记住4个方法,记住执行顺序
process_request(self,request) #最主要的方法
process_view(self, request, view_func, view_args, view_kwargs)
process_exception(self, request, exception)
process_response(self, request, response) #次要

# 知道即可,用不到
process_template_response(self,request,response)

1.process_request

作用: 对所有的请求方法进行同一处理

定义两个中间件类进行执行顺序的测试:

1.先执行中间件的process_request方法:
	中间件1的process_request --> 中间件2的process_request
2.再执行视图函数:
	home

1 在应用中创建一个py文件,名字随意 比如: mymiddleware.py

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect,HttpResponse

class MD1(MiddlewareMixin):
    def process_request(self,request):
        print('MD1--process_request')
        # return None
        # 如果return None,那么程序会自动执行到下一个中间件的process_request方法
        # 如果return的一个httpResponse对象,那么不会再执行后续中间件的process_request方法了,而是直接响应回去
        return HttpResponse('xxxx')

class MD2(MiddlewareMixin):
    def process_request(self,request):
        print('MD2--process_request')

配置:settings.py中的middleware

MIDDLEWARE = [
    # 将自己定义的中间件放到最后,为了方便使用内置中间件中对request对象封装的属性和方法
    'app01.mymiddleware.MD1',  # 配置自定义中间件
    'app01.mymiddleware.MD2',  # 配置自定义中间件
]

2.process_response

作用: 对所有的响应方法进行处理

定义两个中间件类进行执行顺序的测试:

1.先执行中间件的process_request方法:
	中间件1的process_request --> 中间件2的process_request
2.再执行视图函数:
	home
3.倒序执行process_response方法:
	中间件2的process_response --> 中间件1的process_response

中间件mymiddleware.py代码

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect,HttpResponse

class MD1(MiddlewareMixin):
    def process_request(self,request):
        print('MD1--process_request')

    def process_response(self,requset, response):
        """
        :param requset:   请求对象
        :param response:  响应对象,视图函数的响应对象 -- HttpResponse对象
        # render(request, 'home.html')
        :return:
        """
        print('MD1--process_response')
        # print(dir(response)) #response对象中的方法
        # print(response.content) #html中内容
        
        # 处理响应数据:加响应头键值对,控制响应状态码等等
        ret = response
        response['xx'] = 'oo'
        
        return ret  # 必须return一个httpResponse对象,

class MD2(MiddlewareMixin):
    def process_request(self,request):
        print('MD2--process_request')

    def process_response(self, requset, response):
        print('MD2--process_response')
        return response

3.process_view

作用: 对后续要执行的视图函数中的参数进行加工处理

定义两个中间件类进行执行顺序的测试:

1.先执行中间件的process_request方法:
	中间件1的process_request --> 中间件2的process_request
2.然后执行process_view方法:
	中间件1的process_view --> 中间件2的process_view
3.再执行视图函数:
	home
4.倒序执行process_response方法:
	中间件2的process_response --> 中间件1的process_response

中间件mymiddleware.py代码

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect,HttpResponse

class MD1(MiddlewareMixin):
    def process_request(self,request):
        print('MD1--process_request')

    def process_response(self,requset, response):
        print('MD1--process_response')

        return response  # 必须return一个httpResponse对象,

    def process_view(self, request, view_func, view_args, view_kwargs):
        """
        :param request:    请求对象
        :param view_func:  要被执行的视图函数对象
        :param view_args:   url无名分组正则匹配到的参数数据
        :param view_kwargs: url有名分组正则匹配到的参数数据
        :return:
        """
        print('MD1--process_view')
        print(view_func, view_args, view_kwargs)

        
class MD2(MiddlewareMixin):
    def process_request(self,request):
        print('MD2--process_request')

    def process_response(self, request, response):
        print('MD2--process_response')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('MD2--process_view')

4.process_exception

作用: 对视图中的异常进行统一捕获和处理的(接口...)

定义两个中间件类进行执行顺序的测试:

1.先执行中间件的process_request方法:
	中间件1的process_request --> 中间件2的process_request
2.然后执行process_view方法:
	中间件1的process_view --> 中间件2的process_view
3.如果视图函数正常,执行视图函数,否则执行第4步:
	home
4.倒序执行process_exception方法:
	中间件2的process_exception --> 中间件1的process_exception
5.倒序执行process_response方法:
	中间件2的process_response --> 中间件1的process_response

中间件mymiddleware.py代码

from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import redirect,HttpResponse

class MD1(MiddlewareMixin):
    def process_request(self,request):
        print('MD1--process_request')

    def process_response(self,requset, response):
        print('MD1--process_response')
        return response  # 必须return一个httpResponse对象,

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('MD1--process_view')

    # 对视图中的异常进行统一捕获和处理的
    def process_exception(self, request, exception):
        print('MD1--process_exception')
        print(exception)  # 视图返回的错误:xxxx --  错误对象,
              
class MD2(MiddlewareMixin):
    def process_request(self,request):
        print('MD2--process_request')

    def process_response(self, request, response):
        print('MD2--process_response')
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        print('MD2--process_view')

    def process_exception(self, request, exception):
        print('MD2--process_exception')
原文地址:https://www.cnblogs.com/jia-shu/p/14589847.html