이 글의 내용은 미들웨어란 무엇일까요? Python의 Django 미들웨어 분석은 참고할만한 가치가 있습니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
공식 성명: 미들웨어는 Django 요청 및 응답을 처리하는 데 사용되는 프레임워크 수준 후크입니다. Django의 입력 및 출력을 전역적으로 변경하기 위한 경량의 저수준 플러그인 시스템입니다. 각 미들웨어 구성 요소는 몇 가지 특정 기능을 수행합니다.
그러나 전반적인 상황에 영향을 미치기 때문에 부적절한 사용은 성능에 영향을 미칠 수 있으므로 주의가 필요합니다.
미들웨어는 뷰 기능 실행 전후에 몇 가지 추가 작업을 수행하는 데 도움이 됩니다. 이는 본질적으로 클래스에 정의된 여러 메서드가 있는 사용자 정의 클래스입니다. Django 프레임워크는 이러한 메서드를 실행하기 위해 특정 시간을 요청합니다.
미들웨어를 사용해 왔지만 저희가 미처 깨닫지 못했을 뿐입니다. Django 프로젝트의 Settings.py 파일을 열고 아래 그림의 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', ]
MIDDLEWARE 구성 항목은 목록이고 목록은 문자열입니다. 이 문자열은 실제로 클래스, 즉 미들웨어입니다.
그럼 미들웨어의 메소드와 이들 메소드가 언제 실행되는지 살펴보겠습니다.
미들웨어는 다섯 가지 메서드를 정의할 수 있습니다. (주요 메서드는 process_request 및 process_response입니다.)
process_request(self,request)
process_view(self, request, view_func, view_args, View_KWARGS)
Process_template_Response (Self, Request, Response)
Process_Exception (Self, Request, Exception)
Response 上 위 메소드의 반환 값은 None이거나 None일 경우 HttpResponse 객체일 수 있습니다. django에서 정의한 규칙에 따라 계속해서 역방향으로 실행됩니다. HttpResponse 객체인 경우 해당 객체를 사용자에게 직접 반환합니다.
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("第一个里面的 process_request") def process_response(self, request, response): print("第二个里面的 process_response") return response
process_request
미들웨어가 여러 개인 경우 Django가 process_request 메소드를 실행하는 방법을 살펴보겠습니다
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("第一个里面的 process_request") class MD2(MiddlewareMixin): def process_request(self, request): print("第二个里面的 process_request") pass
settings.py의 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', 'middlewares.MD1', # 自定义中间件MD1 'middlewares.MD2' # 自定义中间件MD2 ]
이 시점에서 우리는
第一个里面的 process_request 第二个里面的 process_request app01 中的 index视图
MD1과 MD2의 위치를 바꾸고 뷰에 접근하면 터미널에 다음과 같은 내용이 인쇄되어 있는 것을 볼 수 있습니다.
第二个里面的 process_request 第一个里面的 process_request app01 中的 index视图
결과를 보면, 알아두세요: 뷰 함수는 여전히 마지막에 실행되고, 두 번째 함수는 첫 번째 함수보다 먼저 자체 process_request 메서드를 실행합니다.
두 개의 사용자 정의 미들웨어의 process_request 메소드에서 요청 매개변수를 인쇄하면 둘이 동일한 객체라는 것을 알 수 있습니다.
요약하자면:
미들웨어의 process_request 메소드는 뷰 기능을 실행하기 전에 실행됩니다.
여러 개의 미들웨어를 구성할 경우 MIDDLEWARE에 등록된 순서, 즉 목록의 인덱스 값에 따라 앞에서 뒤로 순서대로 실행됩니다.
서로 다른 미들웨어 간에 전달되는 요청은 모두 동일한 객체입니다
여러 미들웨어의 process_response 메소드는 MIDDLEWARE
역순process_response두 개의 매개변수가 있습니다. 하나는 요청이고 다른 하나는 응답입니다. 요청은 위의 예와 동일한 개체이고 응답은 보기 함수에서 반환된 HttpResponse 개체입니다. 이 메서드의 반환 값도 HttpResponse 개체여야 합니다.
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("第一个里面的 process_request") def process_response(self, request, response): print("第一个里面的 process_response") return response class MD2(MiddlewareMixin): def process_request(self, request): print("第二个里面的 process_request") pass def process_response(self, request, response): print("第二个里面的 process_response") return response
뷰에 액세스하고 터미널 출력을 확인합니다.
第二个里面的 process_request 第一个里面的 process_request app01 中的 index视图 第一个里面的 process_response 第二个里面的 process_response
결과를 보면 다음을 확인할 수 있습니다.
process_response 메소드는 뷰 기능 이후에 실행됩니다. 순서는 MD1 비율입니다. MD2가 먼저 실행됩니다. (이때, settings.py의 MD2가 MD1보다 먼저 등록됩니다.)
여러 미들웨어의 process_response 메소드는 MIDDLEWARE의 등록 순서
역순에 따라 실행됩니다. 즉, 첫 번째 미들웨어의 process_request 메소드가 실행됩니다. process_response 메소드가 가장 나중에 실행되고, 마지막 미들웨어의 process_request 메소드가 마지막으로 실행되고, process_response 메소드가 가장 먼저 실행됩니다.
process_viewprocess_view(self, request, view_func, view_args, view_kwargs)
request는 HttpRequest 객체입니다.
view_func는 Django가 곧 사용할 뷰 함수입니다. (문자열로서의 함수 이름이 아닌 실제 함수 객체입니다.)
view_args是将传递给视图的位置参数的列表.
view_kwargs是将传递给视图的关键字参数的字典。 view_args和view_kwargs都不包含第一个视图参数(request)。
Django会在调用视图函数之前调用process_view方法。
它应该返回None或一个HttpResponse对象。 如果返回None,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后在执行相应的视图。 如果它返回一个HttpResponse对象,Django不会调用适当的视图函数。 它将执行中间件的process_response方法并将应用到该HttpResponse并返回结果。
给MD1和MD2添加process_view方法:
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("第一个里面的 process_request") def process_response(self, request, response): print("第一个里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("第一个中的process_view") print(view_func, view_func.__name__) class MD2(MiddlewareMixin): def process_request(self, request): print("第二个里面的 process_request") pass def process_response(self, request, response): print("第二个里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("第二个中的process_view") print(view_func, view_func.__name__)
访问index视图函数,看一下输出结果:
第二个里面的 process_request 第一个里面的 process_request -------------------------------------------------------------------------------- 第二个 中的process_view <function index at 0x000001DE68317488> index -------------------------------------------------------------------------------- 第一个 中的process_view <function index at 0x000001DE68317488> index app01 中的 index视图 第一个里面的 process_response 第二个里面的 process_response
process_view方法是在process_request之后,视图函数之前执行的,执行顺序按照MIDDLEWARE中的注册顺序从前到后顺序执行的
process_exception(self, request, exception)
该方法两个参数:
一个HttpRequest对象
一个exception是视图函数异常产生的Exception对象。
这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个None也可以是一个HttpResponse对象。如果是HttpResponse对象,Django将调用模板和中间件中的process_response方法,并返回给浏览器,否则将默认处理异常。如果返回一个None,则交给下一个中间件的process_exception方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。
给MD1和MD2添加上这个方法:
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("第一个里面的 process_request") def process_response(self, request, response): print("第一个里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("第一个中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("第一个中的process_exception") class MD2(MiddlewareMixin): def process_request(self, request): print("第二个里面的 process_request") pass def process_response(self, request, response): print("第二个里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("第二个中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("第二个 中的process_exception")
如果视图函数中无异常,process_exception方法不执行。
想办法,在视图函数中抛出一个异常:
def index(request): print("app01 中的 index视图") raise ValueError("呵呵") return HttpResponse("O98K")
在MD1的process_exception中返回一个响应对象:
class MD1(MiddlewareMixin): def process_request(self, request): print("第一个里面的 process_request") def process_response(self, request, response): print("第一个里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("第一个中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("第一个中的process_exception") return HttpResponse(str(exception)) # 返回一个响应对象
看输出结果:
第二个里面的 process_request 第一个里面的 process_request -------------------------------------------------------------------------------- 第二个 中的process_view <function index at 0x0000022C09727488> index -------------------------------------------------------------------------------- 第一个 中的process_view <function index at 0x0000022C09727488> index app01 中的 index视图 呵呵 第一个 中的process_exception 第一个里面的 process_response 第二个里面的 process_response
注意,这里并没有执行MD2的process_exception方法,因为MD1中的process_exception方法直接返回了一个响应对象。
process_template_response(self, request, response)
它的参数,一个HttpRequest对象,response是TemplateResponse对象(由视图函数或者中间件产生)。
process_template_response是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个render()方法(或者表明该对象是一个TemplateResponse对象或等价方法)。
from django.utils.deprecation import MiddlewareMixin class MD1(MiddlewareMixin): def process_request(self, request): print("第一个里面的 process_request") def process_response(self, request, response): print("第一个里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("第一个中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("第一个中的process_exception") def process_template_response(self, request, response): print("第一个中的process_template_response") return response class MD2(MiddlewareMixin): def process_request(self, request): print("第二个里面的 process_request") pass def process_response(self, request, response): print("第二个里面的 process_response") return response def process_view(self, request, view_func, view_args, view_kwargs): print("-" * 80) print("第二个中的process_view") print(view_func, view_func.__name__) def process_exception(self, request, exception): print(exception) print("第二个 中的process_exception") def process_template_response(self, request, response): print("第二个中的process_template_response") return response
views.py中:
def index(request): print("app01 中的 index视图") def render(): print("in index/render") return HttpResponse("O98K") rep = HttpResponse("OK") rep.render = render return rep
访问index视图,终端输出的结果:
第二个里面的 process_request 第一个里面的 process_request -------------------------------------------------------------------------------- 第二个 中的process_view <function index at 0x000001C111B97488> index -------------------------------------------------------------------------------- 第一个 中的process_view <function index at 0x000001C111B97488> index app01 中的 index视图 第一个 中的process_template_response 第二个 中的process_template_response in index/render 第一个里面的 process_response 第二个里面的 process_response
从结果看出:
视图函数执行完之后,立即执行了中间件的process_template_response方法,顺序是倒序,先执行MD1的,在执行MD2的,接着执行了视图函数返回的HttpResponse对象的render方法,返回了一个新的HttpResponse对象,接着执行中间件的process_response方法。
上一部分,我们了解了中间件中的5个方法,它们的参数、返回值以及什么时候执行,现在总结一下中间件的执行流程。
请求到达中间件之后,先按照正序执行每个注册中间件的process_reques方法,process_request方法返回的值是None,就依次执行,如果返回的值是HttpResponse对象,不再执行后面的process_request方法,而是执行当前对应中间件的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两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:
附:Django请求流程图
위 내용은 미들웨어란 무엇입니까? Python에서 Django 미들웨어 분석의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!