Django笔记二十九之中间件介绍
2023/4/24 1:22:13
本文主要是介绍Django笔记二十九之中间件介绍,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
本文首发于公众号:Hunter后端
原文链接:Django笔记二十九之中间件介绍
这一节介绍一下 Django 的中间件。
关于中间件,官方文档的解释为:中间件是一个嵌入 Django 系统的 request 和 response 的钩子框架,是一个能够全局改变 Django 输入/输出的系统。
我们可以这样理解,一个 request 请求发送到 Django 系统的过程中,在经过路由和视图的处理前,会先经过一层处理,这个处理操作可以是日志记录,可以是登录验证甚至你想在系统里定义的功能,这个操作就是中间件实现的功能。
接下来我们将通过一个记录请求的 ip 的功能的介绍来介绍一下中间件的实现流程。
以下是本篇笔记目录:
- 请求经过 Django 然后返回的流程
- HttpRequest 和 HttpResponse 介绍
- 中间件的示例介绍
- 记录访问 ip 的功能实现
1、请求经过 Django 然后返回的流程
首先,前端发起一个请求,这个请求经由 web 服务器转发给 Django 系统,在进入 Django 系统后会先经过一系列的中间件的功能处理。
这个中间件会在 settings.py 里定义,Django 系统默认自带的中间件列表如下:
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', ]
这些中间件我们也可以根据自己的需求自己定义,比如新加一个登录权限,或者日志记录,或者对输入的参数进行格式化处理也可以,或者自己想要设置的其他功能也行,具体怎么设置在后面介绍。
在中间件处理的流程中,请求会被按照顺序从上往下处理。
这个流程过后,一个 request 请求才会被进行 URL 的路径匹配,如果匹配上,再去找相应的 views 视图函数进行数据处理
views 处理完之后,会形成一个 response,返回,然后再次经历这个中间件处理,因为在每一层中间件中都类似于一种嵌套,所以返回 response 的时候,是从下往上再次处理 response 的。
中间件处理结束之后再被返回出去,给到前端。
在这整个流程处理中,可以说中间件是进行了两次操作,一个是进入的时候处理 request,一个是返回的时候处理 response。
2、HttpRequest 和 HttpResponse 介绍
我们先来看一个视图函数:
def time_view(request): now = datetime.datetime.now() html = "<h1>now: %s</h1>abc\nabc" % now return HttpResponse(html)
当 Django 接收到一个请求,系统会创建一个 HttpRequest 对象,这个对象就是上面的视图函数里的输入参数,request
在对数据进行处理后,系统会返回一个 HttpResponse 对象,这个就是我们 return 的内容。
在一个 HttpRequest 对象里,会包含请求的路径、参数、请求方式、 cookie 等一切请求过来时的数据,我们可以在请求的时候根据需要存取。
在返回的 HttpResponse 中,可以是一个 html 页面,也可以是 json 格式的数据,内容是可以自定义的,只要前端可以做相应的处理。
3、中间件的示例介绍
接下来我们定义一个中间件,结构大致如下:
# huter/middleware.py class SimpleMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 在请求进入视图函数前的可以执行一些操作,针对 request print(request.path) response = self.get_response(request) # 在处理完请求后,可以执行一些操作,针对 response # log_response_info() return response
然后我们在 sttings.py 里引入这个中间件,我们放到 MIDDLEWARE 列表的最下面,说明这个中间件会在其他中间件处理完 request 之后再处理:
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', 'hunter.middleware.TestMiddleware', ]
在 SimpleMiddleware 这个类里,call() 函数会自动调用,其中有一行,response = self.get_response(request)
在这一行函数之前,可以对请求的 request 做处理,包括我们前面说的各种功能,比如日志、登录验证、参数格式化等
在这一行函数之后,获取了 response,这个就是视图函数返回的 HttpResponse,我们可以在这里对它的 response.status_code 状态码,和 response.content 做处理
比如前面 time_view 函数返回的内容是一个 JsonResponse:
return JsonResponse({"code": 0})
那么在这里我们可以获取然后处理这个 HttpResponse:
def __call__(self, request): response = self.get_response(request) content = json.loads(response.content) content["msg"] = "success" response.content = json.dumps(content) return response
这里只是一个示例,因为并不是所有的 HttpResponse 都是 json 格式的数据,所以可能需要加一个 try except 做下处理
还有一个功能是我之前做过的,就是在 headers 中加一个特定的字符串,表示是我们系统专有的,用于前端判断,这个很简单,就是在 response 的 headers 参数中加一个键值对:
response.headers['system'] = 'hunter'
以上就是一个最简单的中间件的处理方式。
process_view
除了 call 函数以外,还有一个 process_view() 的函数
这个函数是在 Django 系统调用 views 视图函数前被调用,它的返回值是 None 或者一个 HttpResponse
如果为 None,那么系统会接着调用视图函数,如果是 HttpResponse 作为返回值,说明系统在这里已经处理了请求,不需要再走views视图函数,然后就会直接返回。
我们通过下面的例子来解释这个函数作用。
4、记录访问 ip 的功能实现
假设我们需要禁止某一个或者某一个 ip 列表的请求访问我们的系统
当然,这个操作,在 web 服务器那部分就可以拦截,这里就是单纯举个例子
那么我们这样设置一个 process_view 的功能,在真正执行视图函数(也就是url 匹配上的 view函数)前,取出这个 request 的访问的ip,然后进行判断,如果在 禁止列表,那么则直接返回一个禁止访问的页面。
class TestMiddleware: def __init__(self, get_response): self.get_response = get_response def __call__(self, request): response = self.get_response(request) return response def process_view(self, request, view_func, *view_args, **view_kwargs): EXCLUDE_IPS = ['192.168.1.54'] if 'HTTP_X_FORWARDED_FOR' in request.META: ip = request.META['HTTP_X_FORWARDED_FOR'] else: ip = request.META['REMOTE_ADDR'] if ip in EXCLUDE_IPS: return HttpResponse('<h1>您的ip被禁止</h1>') return None
在这里,我们拿到请求的 ip 地址,去和我们定义的禁止ip列表做比较
如果在禁用列表,则直接返回 HttpResponse,不接着请求我们的服务来
否则,就返回 None,系统接收到 None 之后,会接着往下处理。
如果想获取更多后端相关文章,可扫码关注阅读:
这篇关于Django笔记二十九之中间件介绍的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-12-20go-zero 框架的 RPC 服务 启动start和停止 底层是怎么实现的?-icode9专业技术文章分享
- 2024-12-19Go-Zero 框架的 RPC 服务启动和停止的基本机制和过程是怎么实现的?-icode9专业技术文章分享
- 2024-12-18怎么在golang中使用gRPC测试mock数据?-icode9专业技术文章分享
- 2024-12-15掌握PageRank算法核心!你离Google优化高手只差一步!
- 2024-12-15GORM 中的标签 gorm:"index"是什么?-icode9专业技术文章分享
- 2024-12-11怎么在 Go 语言中获取 Open vSwitch (OVS) 的桥接信息(Bridge)?-icode9专业技术文章分享
- 2024-12-11怎么用Go 语言的库来与 Open vSwitch 进行交互?-icode9专业技术文章分享
- 2024-12-11怎么在 go-zero 项目中发送阿里云短信?-icode9专业技术文章分享
- 2024-12-11怎么使用阿里云 Go SDK (alibaba-cloud-sdk-go) 发送短信?-icode9专业技术文章分享
- 2024-12-10搭建个人博客网站之一、使用hugo创建个人博客网站