这一篇教程,我们一起来了解Django的上下文处理器(Context Processor)和中间件(Middleware)。
对于这两块内容,我们最好先了解概念和原理,才能比较好的去应用它们。
一、上下文处理器(Context Processor)
上下文处理器也称作上下文渲染器。
我个人认为处理比渲染更容易理解,而且英文中“Processor”的意思是处理,“Render”的意思是渲染。
但是称为上下文渲染器也有道理,渲染更接近于使用场景。
Django中的Context Processor主要是应用于模板,完成页面的绘制的一些处理,也就是所说的页面渲染。
还有,上下文又是什么?
这个概念,感觉很难懂。
从语文的角度来说,上下文是语境;
同一句话,在不同的语境中,会有不同的意思。
例如,ipipgo考试成绩100分,爸爸说“干得漂亮”,这是表扬的意思。
而ipipgo考试成绩0分,爸爸说“干得漂亮”,这是讽刺的意思。
所以,同样的一句话,我们需要和上文联系到一起才能明白真正的意思。
从计算机编程角度来说,上下文是环境。
也就是说,同一段处理程序对于不同的环境,反馈出不同的处理结果。
借用网上的一个例子:用户访问站点的时候,站点的所有页面上都要能够显示这个用户自己的IP地址。
这样的功能,我们需要从请求(request)中获取到访问用户的IP地址,然后呈现到页面中。
也许大家能够想到,我们可以在每个页面对应的视图函数中进行这个处理,但是未免太过麻烦。
最好的方式是将处理过程定义一次,就能够在每个页面中使用。
此时,我们可以通过自定义一个上下文处理器帮助我们完成。
面对不同来源的用户通过同一个处理器完成页面上不同IP地址的渲染。
1、创建上下文处理器
在项目文件夹(“wsgi.py”所在的文件夹)新建一个文件“context_processor.py”。
在这个文件中添加获取用户IP地址的代码。
示例代码:
def getuserip(request): ip = request.META['REMOTE_ADDR'] if ip == '127.0.0.1': return {'user_type': '本机用户'} return {'user_type': '外部用户(%s)' % ip}
注意:上下文处理器必须返回一个字典。
2、将上下文处理器添加到模板设置
打开文件“settings.py”,在模板设置中添加处理器中的函数。
TEMPLATES = [ { ...省略部分代码... 'OPTIONS': { 'context_processors': [ ...省略部分代码... <strong>'MyProject.context_processor.getuserip'</strong> ], }, }, ]
上方代码中,红色部分为新增代码。
3、在页面模板中添加标记
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8"> <title>首页</title> </head> <body> 当前访问用户:<strong>{{ user_type }}</strong> </body> </html>
完成上述代码后,Django调用模板时会先通过上下文处理器进行处理,并将处理后返回的数据字典传入模板,通过模板标记获取数据。
此时,我们就可以打开开发服务器,进行访问测试了。
注意:如果需要允许外部访问,需要监听所有IP地址,服务器启动命令为:runserver 0.0.0.0:端口号
,也可以简写为runserver 0:端口号(Win10无效)
。
本机访问结果:
外部访问结果:(例如手机)
二、中间件(Middleware)
中间件,我们需要搞清楚它在什么中间,起到什么作用?
根据官方文档的说法,中间件是请求(request)与响应(response)之间的钩子(hooks)框架。
…又多了个钩子。
个人理解钩子实际上就是挂在主程序上的监控程序,当主程序运行中满足了钩子的触发条件时,执行钩子的处理程序。
在官方文档中,给出的中间件示例非常简单直观,并且包含了两种写法。
1、以函数的形式定义中间件。
示例代码:
<span class="k">def</span> <span class="nf">simple_<span class="highlighted">middleware</span></span><span class="p">(</span><span class="n">get_response</span><span class="p">):</span> <span class="c1"># One-time configuration and initialization.</span> <span class="k">def</span> <span class="nf"><span class="highlighted">middleware</span></span><span class="p">(</span><span class="n">request</span><span class="p">):</span> <span class="c1"># Code to be executed for each request before</span> <span class="c1"># the view (and later <span class="highlighted">middleware</span>) are called.</span> <span class="n">response</span> <span class="o">=</span> <span class="n">get_response</span><span class="p">(</span><span class="n">request</span><span class="p">)</span> <span class="c1"># Code to be executed for each request/response after</span> <span class="c1"># the view is called.</span> <span class="k">return</span> <span class="n">response</span> <span class="k">return</span> <span class="n"><span class="highlighted">middleware</span></span>
2、以类的形式定义中间件
<span class="k">class</span> <span class="nc">Simple<span class="highlighted">Middleware</span></span><span class="p">:</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">get_response</span><span class="p">):</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_response</span> <span class="o">=</span> <span class="n">get_response</span> <span class="c1"># One-time configuration and initialization.</span> <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">request</span><span class="p">):</span> <span class="c1"># Code to be executed for each request before</span> <span class="c1"># the view (and later <span class="highlighted">middleware</span>) are called.</span> <span class="n">response</span> <span class="o">=</span> <span class="bp">self</span><span class="o">.</span><span class="n">get_response</span><span class="p">(</span><span class="n">request</span><span class="p">)</span> <span class="c1"># Code to be executed for each request/response after</span> <span class="c1"># the view is called.</span> <span class="k">return</span> <span class="n">response</span>
那么,中间件怎么使用?能起到什么样的作用呢?
依然通过举例说明。
例如,我们发布的项目只允许本机和指定ip访问,不允许外部其他地址的设备访问,就可以通过中间件来实现。
首先,创建一个中间件文件“middleware.py”,并定义访问限制的中间件。
这个文件可以创建一个新的Package进行存放,例如:MW。
示例代码:
from django.http import HttpResponseForbidden class AaccessRestrictionMiddleware: def __init__(self, get_response): self.get_response = get_response self.wite_ip = ['127.0.0.1', '192.168.31.18'] # 初始化ip地址白名单 def __call__(self, request): ip = request.META['REMOTE_ADDR'] # 获取访问用户的ip if ip not in self.wite_ip: # 如果ip不在白名单中 return HttpResponseForbidden('您被禁止访问!') # 返回响应 response = self.get_response(request) return response
然后,我们打开文件“settings.py”,在中间件设置中添加中间件的类。
示例代码:
MIDDLEWARE = [ 'MW.middleware.AaccessRestrictionMiddleware', ...省略其他中间件... ]
通过以上操作,我们就可以限制只有IP白名单中的用户才能够访问我们的项目。
中间件比较像游戏的外挂程序,游戏主程序的执行过程中一旦满足触发外挂的情形出现,外挂就会执行相应的处理。但是,外挂并不会改变主程序,当我们不需要外挂的时候,只需要移除外挂程序,主程序依然能够正常的执行。
神龙|纯净稳定代理IP免费测试>>>>>>>>天启|企业级代理IP免费测试>>>>>>>>IPIPGO|全球住宅代理IP免费测试