美文网首页django
Django中间件

Django中间件

作者: 大爷的二舅 | 来源:发表于2018-03-24 17:10 被阅读166次

    中间件是Django请求/响应处理的钩子框架。 这是一个轻量级的低级插件系统,用于全局改变Django的输入或输出。

    每个中间件组件都负责完成一些特定的功能。 例如,Django包含一个中间件组件AuthenticationMiddleware,它使用会话将用户与请求关联起来。

    本文档介绍了中间件的工作方式,如何激活中间件以及如何编写自己的中间件。 Django附带一些内置的中间件,您可以立即使用它们。 请参阅本章稍后的“可用中间件”。

    激活中间件

    要激活中间件组件,请将其添加到Django设置中的MIDDLEWARE_CLASSES列表中。

    在MIDDLEWARE_CLASSES中,每个中间件组件都由一个字符串表示:中间件类名的完整Python路径。 例如,以下是由django-admin startproject创建的默认值:

    MIDDLEWARE_CLASSES = [
        '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',
    ]
    

    Django安装不需要任何中间件 - 如果您愿意,MIDDLEWARE_CLASSES可以为空 - 但强烈建议您至少使用CommonMiddleware。

    MIDDLEWARE_CLASSES中的顺序很重要,因为中间件可以依赖于其他中间件。 例如,AuthenticationMiddleware将认证用户存储在会话中; 因此,它必须在SessionMiddleware之后运行。 有关Django中间件类的排序的一些常见提示,请参阅本章后面的“中间件排序”。

    挂钩和应用程序订单

    在请求阶段,在调用视图之前,Django按照MIDDLEWARE_CLASSES中自上而下的顺序应用中间件。 两个钩子可用:

    • process_request()
    • process_view()

    在响应阶段,在调用视图之后,中间件从下往上以相反的顺序应用。 三个挂钩可供选择:

    • process_exception()
    • process_template_response()
    • process_response()

    如果你愿意,你也可以把它想象成一个洋葱:每个中间件类都是一个包装视图的图层。 每个钩子的行为如下所述。

    编写自己的中间件

    编写自己的中间件很容易。 每个中间件组件都是一个Python类,它定义了以下一种或多种方法:

    process_request

    方法:process_request(request)

    • 请求是一个HttpRequest对象。
    • 在Django决定执行哪个视图之前,每个请求都会调用process_request()。

    它应该返回None或HttpResponse对象。 如果返回None,Django将继续处理该请求,执行任何其他process_request()中间件,然后执行process_view()中间件,最后执行相应的视图。

    如果它返回一个HttpResponse对象,Django不会打扰任何其他请求,视图或异常中间件或适当的视图; 它会将响应中间件应用于该HttpResponse,并返回结果。

    process_view

    方法:process_view(request,view_func,view_args,view_kwargs)

    • 请求是一个HttpRequest对象。
    • view_func是Django即将使用的Python函数。 (它是实际的函数对象,而不是函数的名称作为字符串。)
    • view_args是一个将传递给视图的位置参数列表。
    • view_kwargs是将传递给视图的关键字参数的字典。
    • view_args和view_kwargs都不包含第一个视图参数(请求)。 在Django调用视图之前调用process_view()。 它应该返回None或HttpResponse对象。 如果返回None,Django将继续处理此请求,执行任何其他process_view()中间件,然后执行相应的视图。

    如果它返回一个HttpResponse对象,Django不会打扰调用任何其他视图或异常中间件或适当的视图; 它会将响应中间件应用于该HttpResponse,并返回结果。

    在中间件内部从process_request或process_view访问request.POST会阻止任何视图在中间件能够修改请求的上传处理程序之后运行,并且通常应该避免。

    CsrfViewMiddleware类可以被认为是一个例外,因为它提供了csrf_exempt()和csrf_protect()装饰器,它们允许视图明确地控制CSRF验证应该发生在哪一点。

    process_template_response

    方法:process_template_response(request,response)

    • 请求是一个HttpRequest对象。
    • 响应是由Django视图或中间件返回的TemplateResponse对象(或等效对象)。
      如果响应实例具有render()方法,则表示它是TemplateResponse或等效的,process_template_response()在视图执行完毕后立即被调用。

    它必须返回一个实现渲染方法的响应对象。 它可以通过改变response.template_name和response.context_data来改变给定的响应,或者它可以创建并返回一个全新的TemplateResponse或等价物。

    您不需要明确呈现响应 - 响应将在所有模板响应中间件被调用后自动呈现。

    中间件在响应阶段以相反的顺序运行,其中包括process_template_response()。

    process_response

    方法: process_response(request, response)

    • 请求是一个HttpRequest对象。
    • 响应是由Django视图或中间件返回的HttpResponse或StreamingHttpResponse对象。 process_response()在所有响应返回浏览器之前被调用。 它必须返回一个HttpResponse或StreamingHttpResponse对象。 它可以改变给定的响应,也可以创建并返回一个全新的HttpResponse或StreamingHttpResponse。

    与process_request()和process_view()方法不同,即使跳过同一中间件类的process_request()和process_view()方法(因为较早的中间件方法返回了HttpResponse),process_response()方法也会始终被调用。 特别是,这意味着您的process_response()方法不能依赖process_request()中完成的设置。

    最后,请记住,在响应阶段,中间件以相反的顺序应用,从下到上。 这意味着在MIDDLEWARE_CLASSES结尾定义的类将首先运行。

    处理流式响应

    与HttpResponse不同,StreamingHttpResponse没有内容属性。 因此,中间件不能再假设所有的响应都会有一个内容属性。 如果他们需要访问内容,他们必须测试流式响应并相应地调整其行为:

    if response.streaming:
       response.streaming_content = wrap_streaming_content(response.streaming_content)
    else:
       response.content = alter_content(response.content)
    

    应该假定streaming_content太大而不能保存在内存中。 响应中间件可以将其包装在新的生成器中,但不能使用它。 包装通常如下实施:

    def wrap_streaming_content(content):
        for chunk in content:
            yield alter_content(chunk)
    

    #######process_exception
    方法:process_exception(request,exception)

    • 请求是一个HttpRequest对象。

    • 异常是由视图函数引发的Exception对象。
      Django在视图引发异常时调用process_exception()。 process_exception()应该返回None或HttpResponse对象。 如果它返回一个HttpResponse对象,则将应用模板响应和响应中间件,并将生成的响应返回给浏览器。 否则,默认的异常处理就开始了。

    中间件再一次在响应阶段以相反的顺序运行,其中包括process_exception。 如果异常中间件返回响应,则该中间件上的中间件类将不会被调用。

    __init__

    大多数中间件类不需要初始化器,因为中间件类基本上是process_ *methods的占位符。 如果你确实需要一些全局状态,你可以使用__init__来设置。 不过,请记住一些注意事项:

    1. Django无需任何参数即可初始化您的中间件,因此您无法将__init__定义为需要任何参数。
    2. 与每个请求调用一次的process_ *方法不同,当Web服务器响应第一个请求时,__init__只会被调用一次。
    将中间件标记为未使用

    在运行时确定是否应使用中间件有时很有用。 在这些情况下,您的中间件的init方法可能会引发django.core.exceptions.MiddlewareNotUsed。 然后,Django将从中间件进程中移除该中间件,并在DEBUG设置为True时将调试消息记录到django.request记录器中。

    附加指南
    • 中间件类不需要任何子类。

    • 中间件类可以在您的Python路径上的任何地方居住。 所有的Django关心的是MIDDLEWARE_CLASSES设置包括它的路径。

    • 请随意查看Django可用的中间件以获取示例。

    • 如果您编写一个您认为对其他人有用的中间件组件,请为社区做贡献! 让我们知道,我们会考虑将其添加到Django。

    相关文章

      网友评论

        本文标题:Django中间件

        本文链接:https://www.haomeiwen.com/subject/qtsmqftx.html