中间件的运行流程图:

1.编写类
1.1 在项目根目录创建 utils

1.2 在utils 下的 md.py 中创建类。可以写在任意的目录:自定义的类、继承一个类**(推荐)**
from django.utils.deprecation import MiddlewareMixin
class KeLaMiddleware(MiddlewareMixin):
def process_request(self, request): pass
def process_view(self, request, view, *args, **kwargs): pass
def process_response(self, request, response): return response
|
2.注册
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', "utils.md.KeLaMiddleware" ]
|
3.测试
from django.utils.deprecation import MiddlewareMixin
class KeLaMiddleware(MiddlewareMixin):
def process_request(self, request): print("KeLa.process_request")
def process_view(self, request, view, *args, **kwargs): print("KeLa.process_view",view, *args, **kwargs)
def process_response(self, request, response): print("KeLa.process_response") return response
|
from django.contrib import admin from django.urls import path from django.shortcuts import HttpResponse
def x1(request): print("视图.x1") return HttpResponse("x1")
def x2(request, v1): print("视图.x2", v1) return HttpResponse("x2")
urlpatterns = [ path('admin/', admin.site.urls), path('x1/', x1), path('x2/<int:v1>/', x2), ]
|
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', "utils.md.KeLaMiddleware" ]
|
4.问题
中间件的功能好像有点像装饰器【底层源码闭包】
基于中间件可以做什么?
根据请求周期,对 request 进行赋值,后续方便进行调用。
根据请求周期,对业务逻辑代码进行自定义,决定是否可以继续向后
return None,继续向后走
return HttpResponse对象
return HttpResponse("...") return render("...") -> HttpResponse("...") return JsonReponse("...") -> HttpResponse("...")
|
根据请求周期,对返回给用户浏览器的数据进行自定义:删除内容、增加、cookie、响应头…
这个中间件和nginx apache这样的中间件概念一样吗?比如做前置代理,做https
Django中间件 / 拦截器 / RequestHanler
|
中间件可以跨语言调用吗?比如别人不是用python 写的,但是可以给我们的django 项目用?
Django中间件 ... 架构中间件: Django + redis(C语言)
|
中间件只要两层,不要中间那个process.riew行不行,是不是有些特定场合需要返回最后一层
那Django内置的中间件完成了些什么功能?
1.1.2 “不正常”

如果用户向我的网站请求时,如果访问URL:
- /x1/
- /x2/
- /x3/ ,比如携带凭证token,有凭证继续,无凭证返回无权访问。
http://127.0.0.1:8000/x2/12/ http://127.0.0.1:8000/x2/12/?xxx=123
http://127.0.0.1:8000/x3/?token=12938791923981723123
|
from django.utils.deprecation import MiddlewareMixin from django.shortcuts import HttpResponse
class KeLaMiddleware(MiddlewareMixin):
def process_request(self, request): if request.path_info == "/x3/": token = request.GET.get('token') if token == "12938791923981723123": return else: return HttpResponse("无权访问")
|
如果用户向我的网站请求时,如果访问URL:
class KeLaMiddleware(MiddlewareMixin):
def process_request(self, request): if request.path_info.startswith("/x2/"): token = request.GET.get('token') if token == "12938791923981723123": return else: return HttpResponse("无权访问")
|
class KeLaMiddleware(MiddlewareMixin):
def process_view(self, request, view, *args, **kwargs): url_name = request.resolver_match.url_name if url_name == "x2": token = request.GET.get('token') if token == "12938791923981723123": return else: return HttpResponse("无权访问")
|
关于自定义prcess_response,一般用于对请求要返回的数据进行修改。
class KeLaMiddleware(MiddlewareMixin):
def process_response(self, request, response): response["xx"] = "wupeiqi" return response
|
1.2 使用(几乎不用)
class KeLaMiddleware(MiddlewareMixin):
def process_exception(self, request, exception): print(request) print(exception, type(exception)) return HttpResponse("错误了")
|
def x1(request): print("视图.x1") return HttpResponse("x1")
|
class MyHttpResponse: def __init__(self, body): self.body = body
def render(self): return HttpResponse(self.body)
def x1(request): print("视图.x1") return MyHttpResponse("x1")
|
class KeLaMiddleware(MiddlewareMixin):
def process_template_response(self, request, response): return response
|
def x1(request): print("视图.x1") return HttpResponse("源代码-x1")
def x2(request, v1): return HttpResponse("源代码-x2")
def x3(request): return HttpResponse("源代码-x3")
|
class MyHttpResponse: def __init__(self, body): self.body = body
def render(self): return HttpResponse(self.body)
def x1(request): print("视图.x1") return MyHttpResponse("x1")
def x2(request, v1): return MyHttpResponse("x2")
def x3(request): return MyHttpResponse("x3")
|
class KeLaMiddleware(MiddlewareMixin):
def process_template_response(self, request, response): response.body = f"源代码-{response.body}" return response
|
1.3 源码
1.关于请求

from wsgiref.simple_server import make_server
def run_server(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]
if __name__ == '__main__': httpd = make_server('127.0.0.1', 8000, run_server) httpd.serve_forever()
|
from wsgiref.simple_server import make_server
class Handler: def __init__(self): self.name = "wupeiqi" def __call__(self,environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) return [bytes('<h1>Hello, web!</h1>', encoding='utf-8'), ]
if __name__ == '__main__': obj = Handler() httpd = make_server('127.0.0.1', 8000, obj) httpd.serve_forever()
|

2.启动Django项目WSGIHandler.__init__


3.请求到来WSGIHandler.__call__
流程:中间件的执行、路由匹配、视图函数的执行。
小结
1.7.x源码,底层实现,是基于好几个列表。
4.x源码,
函数的作用域 + 闭包 + 装饰器 面向对象 + __call__方法
|
# 核心 # handler = SecurityMiddleware对象 # __call__ # process_request # get_reponse = SessionMiddleware对象 # process_response # __call__ # process_request # get_reponse = CommonMiddleware对象 # process_response # __call__ # process_request # get_reponse = KeLaMiddleware对象 # process_response
|
答疑
- 没悟透,不需要吾、只需要懂【不需要背+建立】
- 有些难
- 入门,听懂+能用(全家桶)
- 文档,用法没有源码。
- 源码,到底是怎么实现的功能(不修改、扩展)【*】
- 感觉听懂了,但又不清楚,这是不是学源码的正常情况,看B站视频写程序都很简单,也容易懂
- 课下还是得自己分析分析,一定会忘记