> 백엔드 개발 > 파이썬 튜토리얼 > 미들웨어란 무엇입니까? Python에서 Django 미들웨어 분석

미들웨어란 무엇입니까? Python에서 Django 미들웨어 분석

不言
풀어 주다: 2018-09-25 17:02:48
원래의
3179명이 탐색했습니다.

이 글의 내용은 미들웨어란 무엇일까요? 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

process_request에는 요청이라는 하나의 매개변수가 있습니다. 이 요청은 보기 기능의 요청과 동일합니다.

반환 값은 None 또는 HttpResponse 개체일 수 있습니다. 반환값이 None이면 일반적인 프로세스에 따라 진행하고, 다음 미들웨어에 넘겨 처리하도록 한다. HttpResponse 객체라면 Django는 view 함수를 실행하지 않고 해당 객체를 브라우저에 반환한다.

미들웨어가 여러 개인 경우 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 메소드는 뷰 기능을 실행하기 전에 실행됩니다.

  1. 여러 개의 미들웨어를 구성할 경우 MIDDLEWARE에 등록된 순서, 즉 목록의 인덱스 값에 따라 앞에서 뒤로 순서대로 실행됩니다.

  2. 서로 다른 미들웨어 간에 전달되는 요청은 모두 동일한 객체입니다

  3. 여러 미들웨어의 process_response 메소드는 MIDDLEWARE

    역순
  4. 의 등록 순서에 따라 실행됩니다. 즉, 첫 번째 미들웨어 process_request 메소드 가장 먼저 실행되고, process_response 메소드가 마지막에 실행됩니다. 마지막 미들웨어의 process_request 메소드가 마지막으로 실행되고, process_response 메소드가 가장 먼저 실행됩니다.

process_response두 개의 매개변수가 있습니다. 하나는 요청이고 다른 하나는 응답입니다. 요청은 위의 예와 동일한 개체이고 응답은 보기 함수에서 반환된 HttpResponse 개체입니다. 이 메서드의 반환 값도 HttpResponse 개체여야 합니다.

위의 M1 및 M2에 process_response 메소드를 추가합니다.

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)

이 메소드에는 4개의 매개변수가 있습니다

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

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(用的比较少)

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 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
최신 이슈
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿