美文网首页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 中间件

    1.什么是Django的中间件? django 中的中间件(middleware),在django中,中间件其实就...

  • 13.中间件和上下文处理器

    中间件 中间件的引入image.png django中的中间件django 中的中间件(middleware),在...

  • 什么是Django中的中间件?

    什么是Django中的中间件? 中间件 Django中的中间件是一个轻量级、底层的插件系统,可以介入Django的...

  • Django_中间件

    Django的中间件的简介 Django的中间件类似于linux中的管道符Django的中间件实质就是一个类,类之...

  • django middleware

    参考:Django 源码学习(3)——中间件Django Middleware官方文档Django==2.0.4源...

  • Django的生命周期

    Django的生命周期 一. Django HTTP请求流程图 二. 中间件 什么是中间件 中间件是一个用来处理D...

  • Django 十一

    目录 1.cbv加装饰器 总结 2.中间件介绍和常用内置中间件 3.django内置中间件 4.django自定义...

  • Django中间件和上下文处理器

    中间件的引入:Django中间件(Middleware)是一个轻量级、底层的“插件”系统,可以介入Django的请...

  • Django 中间件

    django 中的中间件(middleware),在django中,中间件其实就是一个类,在请求到来和结束后,dj...

  • 使用 Django 中的 csrf 处理

    Django中有一个django.middleware.csrf.CsrfViewMiddleware中间件提供了...

网友评论

    本文标题:Django中间件

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