django七大中间件的作用,django的组件

  django七大中间件的作用,django的组件

  在前面的课程中,我们已经学习了如何通过修饰view函数来判断用户是否登录,将未登录的用户跳转到登录页面。我们通过向几个特定的视图函数添加装饰器来实现这个需求。不过以后增加的视图功能可能还需要修饰,有点繁琐。

  学完今天的内容,我们可以用更合适的方式实现对所有请求做同样操作的功能。

  中间件简介什么是中间件?官方说法是,中间件是一个框架级的钩子,用于处理Django的请求和响应。它是一个轻量级的底层插件系统,用于在全局范围内改变Django的输入和输出。每个中间件组件负责完成一些特定的功能。

  但因为它影响整个世界,所以需要小心使用,使用不当会影响性能。

  说白了,中间件帮助我们在视图函数执行前后做一些额外的操作。它本质上是一个自定义类,其中定义了几个方法,Django framework会在请求的特定时间执行这些方法。

  我们一直在使用中间件,只是没有注意到而已。打开Django项目的Settings.py文件,看到下图中的中间件配置项。

  中间件=[

   django . middleware . security . security middleware ,

   django . contrib . sessions . middleware . session middleware ,

   django . middleware . common . common middleware ,

   django . middleware . csrf . csrfviewmiddleware ,

   django . contrib . auth . middleware . authenticationmiddleware ,

   django . contrib . messages . middleware . message middleware ,

   django . middleware . click jacking . xframeoptions middleware ,

  ]

  中间件配置项是一个列表,列表中有字符串。这些字符串其实就是类,也就是中间件。

  我们之前已经接触过一个csrf相关的中间件?一开始我们让大家把他评论出来,然后他们提交帖子请求的时候也不会被拒绝。后来学会使用csrf_token后,他们就不再评论这个中间件了。

  然后学习中间件中的方法,以及何时执行。

  自定义中间件中间件可以定义五种方法,分别是:(主要是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)process _ Response(self,request,Response)上述方法的返回值可以是None,也可以是HttpResponse对象。如果没有,它将根据django定义的规则继续向后执行。如果是HttpResponse对象,会直接返回给用户。

  定制一个中间件示例。

  从django.utils.deprecation导入MiddlewareMixin

  MD1类(MiddlewareMixin):

  def process_request(自身,请求):

  打印(“MD1中的process_request”)

  def process_response(自身、请求、响应):

  打印(“MD1中的process_response”)

  返回响应

  Process_requestprocess_request有一个参数,就是request。该请求与查看功能中的请求相同。

  它的返回值可以是None或HttpResponse对象。如果返回值为None,则按照正常流程进行,交给下一个中间件。如果是HttpResponse对象,Django不会执行view函数,而是将对应的对象返回给浏览器。

  我们来看看Django是如何在多个中间件中执行process_request方法的。

  从django.utils.deprecation导入MiddlewareMixin

  MD1类(MiddlewareMixin):

  def process_request(自身,请求):

  打印(“MD1中的process_request”)

  MD2类(MiddlewareMixin):

  def process_request(自身,请求):

  打印(“MD2中的process_request”)

  及格

  在settings.py的中间件配置项中注册以上两个自定义中间件:

  中间件=[

   django . middleware . security . security middleware ,

   django . contrib . sessions . middleware . session middleware ,

   django . middleware . common . common middleware ,

   django . middleware . csrf . csrfviewmiddleware ,

   django . contrib . auth . middleware . authenticationmiddleware ,

   django . contrib . messages . middleware . message middleware ,

   django . middleware . click jacking . xframeoptions middleware ,

  中间件。 MD1 ,#自定义中间件MD1

  中间件。MD2 #定制中间件MD2

  ]

  此时,当我们访问一个视图时,我们会发现终端中打印了以下内容:

  MD1中的流程请求

  MD2中的流程请求

  在app01的索引视图中,改变MD1和MD2的位置,然后访问一个视图,你会发现终端中打印的内容如下:

  MD2中的流程请求

  MD1中的流程请求

  根据app01中index视图的结果,我们知道view函数是最后执行的,MD2在MD1之前执行了自己的process_request方法。

  打印两个自定义中间件的process_request方法中的request参数,你会发现它们是同一个对象。

  总而言之:

  中间件的process_request方法在view函数执行之前执行。配置多个中间件时,会按照中间件中的注册顺序,也就是列表的索引值,从前到后执行。不同中间件之间传递的请求都是同一个对象。

  多个中间件中的process_response方法按照在中间件中的注册顺序以相反的顺序执行,即首先执行第一个中间件的process_request方法,最后执行其process_response方法,最后执行最后一个中间件的process_request方法,首先执行其process_response方法。

  Process_response它有两个参数,一个是请求,一个是响应。request是上例中的同一个对象,response是view函数返回的HttpResponse对象。此方法的返回值也必须是HttpResponse对象。

  将process_response方法添加到上面的M1和M2中:

  从django.utils.deprecation导入MiddlewareMixin

  MD1类(MiddlewareMixin):

  def process_request(自身,请求):

  打印(“MD1中的process_request”)

  def process_response(自身、请求、响应):

  打印(“MD1中的process_response”)

  返回响应

  MD2类(MiddlewareMixin):

  def process_request(自身,请求):

  打印(“MD2中的process_request”)

  及格

  def process_response(自身、请求、响应):

  打印(“MD2中的process_response”)

  返回响应

  访问一个视图并查看终端的输出:

  MD2中的流程请求

  MD1中的流程请求

  app01中的索引视图

  MD1中的流程响应

  从结果中可以看到MD2中的process_response:

  process_response方法在view函数之后执行,顺序是MD1在MD2之前执行。(此时在settings.py中MD2先于MD1注册)

  多个中间件中的process_response方法按照在中间件中的注册顺序以相反的顺序执行,即首先执行第一个中间件的process_request方法,最后执行其process_response方法,最后执行最后一个中间件的process_request方法,首先执行其process_response方法。

  process_viewprocess_view(自身,请求,视图功能,视图参数,视图参数)

  该方法有四个参数。

  是HttpRequest对象。

  View_func是Django即将使用的视图函数。(是实际的函数对象,不是字符串形式的函数名。)

  View_args是将传递给视图的位置参数列表。

  View_kwargs是将被传递给视图的关键字参数的字典。view_args和view_kwargs都不包含第一个视图参数(请求)。

  Django会在调用视图函数之前调用process_view方法。

  它应该返回None或一个HttpResponse对象。如果没有返回,Django将继续处理这个请求,执行任何其他中间件的process_view方法,然后执行相应的视图。如果它返回一个HttpResponse对象,Django将不会调用适当的视图函数。它将执行中间件的process_response方法,并将其应用于HttpResponse,然后返回结果。

  将process_view方法添加到MD1和MD2:

  从django.utils.deprecation导入MiddlewareMixin

  MD1类(MiddlewareMixin):

  def process_request(自身,请求):

  打印(“MD1中的process_request”)

  定义流程_响应(自身、请求、响应):

  打印( MD1里面的流程_响应)

  返回响应

  def process_view(self,request,view_func,view_args,view_kwargs):

  打印(- * 80)

  打印( MD1中的流程视图)

  print(view_func,view_func .__name__)

  MD2类(MiddlewareMixin):

  定义流程请求(自身,请求):

  打印( MD2里面的process _ request’)

  及格

  定义流程_响应(自身、请求、响应):

  打印( MD2里面的流程_响应)

  返回响应

  def process_view(self,request,view_func,view_args,view_kwargs):

  打印(- * 80)

  打印( MD2中的流程视图)

  print(view_func,view_func .__name__)

  访问指数视图函数,看一下输出结果:

  MD2里面的流程_请求

  MD1里面的流程_请求

  -

  MD2中的流程_视图

  0x000001DE68317488索引处的函数索引

  -

  MD1中的流程_视图

  0x000001DE68317488索引处的函数索引

  app01中的指数视图

  MD1里面的流程_响应

  MD2里面的流程_响应

  流程_视图方法是在流程_请求之后,视图函数之前执行的,执行顺序按照中间件中的注册顺序从前到后顺序执行的

  进程异常进程异常(自身,请求,异常)

  该方法两个参数:

  一个对象对象

  一个例外是视图函数异常产生的例外对象。

  这个方法只有在视图函数中出现异常了才执行,它返回的值可以是一个没有人也可以是一个HttpResponse对象。如果是HttpResponse对象姜戈将调用模板和中间件中的流程_响应方法,并返回给浏览器,否则将默认处理异常。如果返回一个没有,则交给下一个中间件的流程_异常方法来处理异常。它的执行顺序也是按照中间件注册顺序的倒序执行。

  给MD1和MD2添加上这个方法:

  从django.utils.deprecation导入MiddlewareMixin

  MD1类(MiddlewareMixin):

  定义流程请求(自身,请求):

  打印( MD1里面的process _ request’)

  定义流程_响应(自身、请求、响应):

  打印( MD1里面的流程_响应)

  返回响应

  def process_view(self,request,view_func,view_args,view_kwargs):

  打印(- * 80)

  打印( MD1中的流程视图)

  print(view_func,view_func .__name__)

  定义进程_异常(自身、请求、异常):

  打印(例外)

  打印( MD1中的process _ exception’)

  MD2类(MiddlewareMixin):

  定义流程请求(自身,请求):

  打印( MD2里面的process _ request’)

  及格

  定义流程_响应(自身、请求、响应):

  打印( MD2里面的流程_响应)

  返回响应

  def process_view(self,request,view_func,view_args,view_kwargs):

  打印(- * 80)

  打印( MD2中的流程视图)

  print(view_func,view_func .__name__)

  定义进程_异常(自身、请求、异常):

  打印(例外)

  打印( MD2中的process _ exception’)

  如果视图函数中无异常,流程_异常方法不执行。

  想办法,在视图函数中抛出一个异常:

  定义索引(请求):

  打印(应用01中的指数视图)

  提高值错误(呵呵)

  返回HttpResponse(O98K )在MD1的流程_异常中返回一个响应对象:

  MD1类(MiddlewareMixin):

  定义流程请求(自身,请求):

  打印( MD1里面的process _ request’)

  定义流程_响应(自身、请求、响应):

  打印( MD1里面的流程_响应)

  返回响应

  def process_view(self,request,view_func,view_args,view_kwargs):

  打印(- * 80)

  打印( MD1中的流程视图)

  print(view_func,view_func .__name__)

  定义进程_异常(自身、请求、异常):

  打印(例外)

  打印( MD1中的process _ exception’)

  返回HttpResponse(str(exception)) #返回一个响应对象

  看输出结果:

  MD2里面的流程_请求

  MD1里面的流程_请求

  -

  MD2中的流程_视图

  0x0000022C09727488索引处的函数索引

  -

  MD1中的流程_视图

  0x0000022C09727488索引处的函数索引

  app01中的指数视图

  呵呵

  MD1中的流程_异常

  MD1里面的流程_响应

  MD2里面的流程_响应

  注意,这里并没有执行MD2的流程_异常方法,因为MD1中的流程_异常方法直接返回了一个响应对象。

  流程_模板_响应(用的比较少)流程_模板_响应(自身、请求、响应)

  它的参数,一个对象对象,响应是模板响应对象(由视图函数或者中间件产生)。

  流程_模板_响应是在视图函数执行完成后立即执行,但是它有一个前提条件,那就是视图函数返回的对象有一个渲染()方法(或者表明该对象是一个模板响应对象或等价方法)。

  MD1类(MiddlewareMixin):

  定义流程请求(自身,请求):

  打印( MD1里面的process _ request’)

  定义流程_响应(自身、请求、响应):

  打印( MD1里面的流程_响应)

  返回响应

  def process_view(self,request,view_func,view_args,view_kwargs):

  打印(- * 80)

  打印( MD1中的流程视图)

  print(view_func,view_func .__name__)

  定义进程_异常(自身、请求、异常):

  打印(例外)

  打印( MD1中的process _ exception’)

  返回HttpResponse(str(exception))

  定义流程_模板_响应(自身、请求、响应):

  打印( MD1中的流程_模板_响应)

  返回响应

  MD2类(MiddlewareMixin):

  定义流程请求(自身,请求):

  打印( MD2里面的process _ request’)

  及格

  定义流程_响应(自身、请求、响应):

  打印( MD2里面的流程_响应)

  返回响应

  def process_view(self,request,view_func,view_args,view_kwargs):

  打印(- * 80)

  打印( MD2中的流程视图)

  print(view_func,view_func .__name__)

  定义进程_异常(自身、请求、异常):

  打印(例外)

  打印( MD2中的process _ exception’)

  定义流程_模板_响应(自身、请求、响应):

  打印( MD2中的流程_模板_响应)

  返回响应

  views.py中:

  定义索引(请求):

  打印(应用01中的指数视图)

  定义渲染():

  打印("在索引/呈现中")

  返回HttpResponse(O98K )

  rep=HttpResponse(OK )

  再现渲染=渲染

  退货代表

  访问指数视图,终端输出的结果:

  MD2里面的流程_请求

  MD1里面的流程_请求

  -

  MD2中的流程_视图

  0x000001C111B97488索引处的函数索引

  -

  MD1中的流程_视图

  0x000001C111B97488索引处的函数索引

  app01中的指数视图

  MD1中的流程_模板_响应

  MD2中的流程_模板_响应

  在索引/渲染中

  MD1里面的流程_响应

  MD2里面的流程_响应

  从结果看出:

  视图函数执行完之后,立即执行了中间件的流程_模板_响应方法,顺序是倒序,先执行MD1的,在执行MD2的,接着执行了视图函数返回的HttpResponse对象的提出方法,返回了一个新的HttpResponse对象,接着执行中间件的流程_响应方法。

  中间件的执行流程上一部分,我们了解了中间件中的5个方法,它们的参数、返回值以及什么时候执行,现在总结一下中间件的执行流程。

  请求到达中间件之后,先按照正序执行每个注册中间件的流程请求方法,流程_请求方法返回的值是没有,就依次执行,如果返回的值是HttpResponse对象,不再执行后面的流程_请求方法,而是执行当前对应中间件的流程_响应方法,将HttpResponse对象返回给浏览器。也就是说:如果中间件中注册了6个中间件,执行过程中,第3个中间件返回了一个HttpResponse对象,那么第4,5,6中间件的流程_请求和流程_响应方法都不执行,顺序执行3,2,1中间件的流程_响应方法。

  流程_请求方法都执行完后,匹配路由,找到要执行的视图函数,先不执行视图函数,先执行中间件中的流程_视图方法,流程_视图方法返回没有,继续按顺序执行,所有流程_视图方法执行完后执行视图函数。加入中间件3的流程_视图方法返回了HttpResponse对象,则4,5,6的流程_视图以及视图函数都不执行,直接从最后一个中间件,也就是中间件6的流程_响应方法开始倒序执行。

  流程_模板_响应和流程_异常两个方法的触发是有条件的,执行顺序也是倒序。总结所有的执行流程如下:

  中间件版登录验证中间件版的登录验证需要依靠会话,所以数据库中要有姜戈_session表。

  urls.py

  从django.conf.urls导入全球资源定位器(Uniform Resource Locator)

  从app01导入视图

  urlpatterns=[

  url(r^index/$,观点指数),

  url(r^login/$,views.login,name=login’),

  ]urls.py

  views.py

  快捷方式导入渲染,HttpResponse,重定向

  定义索引(请求):

  返回HttpResponse(“这是索引")

  定义主页(请求):

  返回HttpResponse(“这是家")

  定义登录(请求):

  if request.method==POST :

  用户=请求. POST.get(用户)

  pwd=请求POST.get(pwd )

  如果user==Q1mi 和pwd==123456 :

  # 设置会议

  request.session[用户]=用户

  # 获取跳到登陆页面之前的统一资源定位器

  next_url=请求. GET.get(下一个)

  # 如果有,就跳转回登陆之前的统一资源定位器

  if next_url:

  返回重定向(下一个网址)

  # 否则默认跳转到指数页面

  否则:

  返回重定向(/index/)

  返回render(request,“log in . html”)views . py

  login.html

  !声明文档类型

  html lang=en

  头

  meta charset=UTF-8

  meta http-equiv= x-ua-compatible content= IE=edge

  meta name= viewport content= width=device-width,initial-scale=1

  标题登录页面/标题

  /头

  身体

  表单操作={% url 登录名 %}

  p

  =用户的标签用户名:/标签

  输入类型=text name=user id=user

  /p

  p

  =pwd 的标签密码:/标签

  输入类型=文本名称=pwd id=pwd

  /p

  输入类型=提交值=登录

  /表单

  /body

  /html login.html

  中间件。巴拉圭

  类AuthMD(MiddlewareMixin):

  white_list=[/login/,] #白名单

  balck_list=[/black/,] #黑名单

  定义流程请求(自身,请求):

  快捷方式导入重定向,HttpResponse

  next_url=request.path_info

  print(请求路径信息,请求获取完整路径()

  if next_url in self.white_list或request.session.get(user ):

  返回

  self.balck_list中的elif next_url:

  返回HttpResponse(“这是一个非法的网址”)

  否则:

  返回重定向(/login/?next={} .格式(下一个网址))登录校验中间件

  在settings.py中注册

  中间件=[

  姜戈。中间件。安全。安全中间件,

  姜戈。贡献。会话。中间件。会话中间件,

  姜戈。中间件。常见。通用中间件,

  姜戈。中间件。csrf。 csrfviewmiddleware ,

  姜戈。贡献。auth。中间件。认证中间件,

  姜戈。贡献。消息。中间件。消息中间件,

  中间件 AuthMD ,

  ]settings.py中注册中间件

  AuthMD中间件注册后,所有的请求都要走AuthMD的流程_请求方法。

  访问的统一资源定位器在白名单内或者会议中有用户用户名,则不做阻拦走正常流程;

  如果统一资源定位器在黑名单中,则返回这是一个非法网址的字符串;

  正常的统一资源定位器但是需要登录后访问,让浏览器跳转到登录页面。

  注:AuthMD中间件中需要会话,所以AuthMD注册的位置要在会议中间的下方。

  附:Django请求流程图

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: