[Django 0-1] Core.Handlers 模块

Core.Handlers 模块

这个模块封装了 wsgi,asgi 两个类,分别用于处理外部的请求信息,asgi 提供异步处理能力。

Handler 模块将请求Request封装包裹了Middleware中间件,并将处理结果返回为Response响应对象。

BaseHandler

重要函数

  • load_middleware: 先把 handler 函数套一层 exception handler, 在倒序包裹中间件。支持process_view,process_exception,process_template_response
def load_middleware(self, is_async=False):"""Populate middleware lists from settings.MIDDLEWARE.Must be called after the environment is fixed (see __call__ in subclasses)."""self._view_middleware = []self._template_response_middleware = []self._exception_middleware = []get_response = self._get_response_async if is_async else self._get_responsehandler = convert_exception_to_response(get_response)handler_is_async = is_asyncfor middleware_path in reversed(settings.MIDDLEWARE):middleware = import_string(middleware_path)middleware_can_sync = getattr(middleware, "sync_capable", True)middleware_can_async = getattr(middleware, "async_capable", False)if not middleware_can_sync and not middleware_can_async:raise RuntimeError("Middleware %s must have at least one of ""sync_capable/async_capable set to True." % middleware_path)elif not handler_is_async and middleware_can_sync:middleware_is_async = Falseelse:middleware_is_async = middleware_can_asynctry:# Adapt handler, if needed.# 异步兼容步骤adapted_handler = self.adapt_method_mode(middleware_is_async,handler,handler_is_async,debug=settings.DEBUG,name="middleware %s" % middleware_path,)mw_instance = middleware(adapted_handler)except MiddlewareNotUsed as exc:if settings.DEBUG:if str(exc):logger.debug("MiddlewareNotUsed(%r): %s", middleware_path, exc)else:logger.debug("MiddlewareNotUsed: %r", middleware_path)continueelse:handler = adapted_handlerif mw_instance is None:# 避免你的middleware有问题raise ImproperlyConfigured("Middleware factory %s returned None." % middleware_path)if hasattr(mw_instance, "process_view"):self._view_middleware.insert(0,self.adapt_method_mode(is_async, mw_instance.process_view),)if hasattr(mw_instance, "process_template_response"):self._template_response_middleware.append(self.adapt_method_mode(is_async, mw_instance.process_template_response),)if hasattr(mw_instance, "process_exception"):# The exception-handling stack is still always synchronous for# now, so adapt that way.self._exception_middleware.append(self.adapt_method_mode(False, mw_instance.process_exception),)handler = convert_exception_to_response(mw_instance)handler_is_async = middleware_is_async# Adapt the top of the stack, if needed.handler = self.adapt_method_mode(is_async, handler, handler_is_async)# We only assign to this when initialization is complete as it is used# as a flag for initialization being complete.self._middleware_chain = handler
  • resolve_request: 通过get_resolver得到路由解析器,并将处理结果赋值给request.resolver_match

get_resolver使用了lru_cache装饰器来减少重复计算。

def resolve_request(self, request):"""Retrieve/set the urlconf for the request. Return the view resolved,with its args and kwargs."""# Work out the resolver.if hasattr(request, "urlconf"):urlconf = request.urlconfset_urlconf(urlconf)resolver = get_resolver(urlconf)else:resolver = get_resolver()# Resolve the view, and assign the match object back to the request.resolver_match = resolver.resolve(request.path_info)request.resolver_match = resolver_matchreturn resolver_match
  • _get_response: 调用resolve_request得到处理结果,并将结果赋值给response

看这段源码,你可以知道一个请求是如何被返回的,

  1. 首先得到 urlresolver 解析器,解析请求的 url,得到视图函数和参数。 由于实现了__getitem__可以支持自动解包
  2. 调用process_view函数
  3. 根据配置决定是否开启 atomic
  4. 调用视图函数,并将结果赋值给response
  5. 如果response支持模板渲染,则调用process_template_response函数
  6. 返回response
def _get_response(self, request):"""Resolve and call the view, then apply view, exception, andtemplate_response middleware. This method is everything that happensinside the request/response middleware."""response = Nonecallback, callback_args, callback_kwargs = self.resolve_request(request)# Apply view middlewarefor middleware_method in self._view_middleware:response = middleware_method(request, callback, callback_args, callback_kwargs)if response:breakif response is None:wrapped_callback = self.make_view_atomic(callback)# If it is an asynchronous view, run it in a subthread.if iscoroutinefunction(wrapped_callback):wrapped_callback = async_to_sync(wrapped_callback)try:response = wrapped_callback(request, *callback_args, **callback_kwargs)except Exception as e:response = self.process_exception_by_middleware(e, request)if response is None:raise# Complain if the view returned None (a common error).self.check_response(response, callback)# If the response supports deferred rendering, apply template# response middleware and then render the responseif hasattr(response, "render") and callable(response.render):for middleware_method in self._template_response_middleware:response = middleware_method(request, response)# Complain if the template response middleware returned None# (a common error).self.check_response(response,middleware_method,name="%s.process_template_response"% (middleware_method.__self__.__class__.__name__,),)try:response = response.render()except Exception as e:response = self.process_exception_by_middleware(e, request)if response is None:raisereturn response

WSGIHandler

重要函数
  • __call__: 处理每个进来的请求
def __call__(self, environ, start_response):set_script_prefix(get_script_name(environ))signals.request_started.send(sender=self.__class__, environ=environ)request = self.request_class(environ)response = self.get_response(request)response._handler_class = self.__class__status = "%d %s" % (response.status_code, response.reason_phrase)response_headers = [*response.items(),*(("Set-Cookie", c.output(header="")) for c in response.cookies.values()),]start_response(status, response_headers)if getattr(response, "file_to_stream", None) is not None and environ.get("wsgi.file_wrapper"):# If `wsgi.file_wrapper` is used the WSGI server does not call# .close on the response, but on the file wrapper. Patch it to use# response.close instead which takes care of closing all files.response.file_to_stream.close = response.closeresponse = environ["wsgi.file_wrapper"](response.file_to_stream, response.block_size)return response

ASGIHandler

重要函数
  • handle: 处理每个进来的请求
async def handle(self, scope, receive, send):"""Handles the ASGI request. Called via the __call__ method."""# Receive the HTTP request body as a stream object.try:body_file = await self.read_body(receive)except RequestAborted:return# Request is complete and can be served.set_script_prefix(get_script_prefix(scope))await signals.request_started.asend(sender=self.__class__, scope=scope)# Get the request and check for basic issues.request, error_response = self.create_request(scope, body_file)if request is None:body_file.close()await self.send_response(error_response, send)await sync_to_async(error_response.close)()returnasync def process_request(request, send):response = await self.run_get_response(request)try:await self.send_response(response, send)except asyncio.CancelledError:# Client disconnected during send_response (ignore exception).passreturn response# Try to catch a disconnect while getting response.tasks = [# Check the status of these tasks and (optionally) terminate them# in this order. The listen_for_disconnect() task goes first# because it should not raise unexpected errors that would prevent# us from cancelling process_request().asyncio.create_task(self.listen_for_disconnect(receive)),asyncio.create_task(process_request(request, send)),]await asyncio.wait(tasks, return_when=asyncio.FIRST_COMPLETED)# Now wait on both tasks (they may have both finished by now).for task in tasks:if task.done():try:task.result()except RequestAborted:# Ignore client disconnects.passexcept AssertionError:body_file.close()raiseelse:# Allow views to handle cancellation.task.cancel()try:await taskexcept asyncio.CancelledError:# Task re-raised the CancelledError as expected.passtry:response = tasks[1].result()except asyncio.CancelledError:await signals.request_finished.asend(sender=self.__class__)else:await sync_to_async(response.close)()body_file.close()

可以学习的地方

  • asyncio.wait 的参数return_when=asyncio.FIRST_COMPLETED,可以让任务在第一个完成的时候返回,而不是等待所有任务完成。

总结

Handler 模块封装了 wsgi,asgi 两个类,分别用于处理外部的请求信息,asgi 提供异步处理能力。很好的实现了请求的处理流程,并提供了中间件的功能。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/746483.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

buuctf 部分web题

[b01lers2020]Welcome to Earth 打开网站,停一会会跳转die,了解一下,这就类似一个通关游戏,不能死亡,也就是说进入/die这个网站就意味着题就做不出来了;所以回到上一个网站原网站,查看源码&…

神经网络量化

神经网络量化(Neural Network Quantization)是一种技术,旨在减少神经网络模型的计算和存储资源需求,同时保持其性能。在深度学习中,神经网络模型通常使用高精度的参数(例如32位浮点数)来表示权重…

如何关闭 Visual Studio 双击异常高亮

[问题描述]: 最近 Visual Studio 更新后,双击选中关键字快要亮瞎我的眼睛了 👀👀 [解决方法]: 摸索了一下,找到了关闭的方法:工具 → 选项 → 文本编辑器 → 常规,然后取消 勾选 sel…

红帽认证含金量如何?红帽rhcsa认证证书认可度高吗?

事实上,红帽认证含金量在全球范围内都得到了广泛的认可和重视。许多企业和组织都将红帽认证作为招聘和选拔人才的重要标准之一。持有红帽认证的个人往往能够获得更好的职业机会和更高的薪资水平。此外,红帽认证还被许多政府机构、行业协会和教育机构所认…

888888888888888888后果聚光镜

☞ 通用计算机启动过程 1️⃣一个基础固件:BIOS 一个基础固件:BIOS→基本IO系统,它提供以下功能: 上电后自检功能 Power-On Self-Test,即POST:上电后,识别硬件配置并对其进行自检&#xff0c…

html行内元素(内联元素),块级元素分别有哪些?

html行内元素&#xff08;内联元素&#xff09;&#xff0c;块级元素分别有哪些&#xff1f; 常用的分类包括行内元素&#xff08;内联元素&#xff09;和块级元素。下面是它们的示例列表&#xff1a; 行内元素&#xff08;Inline Elements&#xff09;&#xff1a; <span&…

laravel 表单验证的 exists、unique 去除软删除字段的校验

use Illuminate\Validation\Rule; exists 去除软删除字段的校验 $validator \Validator::make($data, [phone_new > [Rule::exists(users, phone)->whereNull(deleted_at),]], [phone_new.exists > 手机号不存在,]);unique 去除软删除字段的校验 // 新增 email>r…

vue3动态组件未渲染问题

渲染问题 component动态组件写法与vue2写法一致&#xff0c;代码如下&#xff1a; <component :is"componentName"/><script setup>import { ref } from vueimport account from ./user/account.vue// 组件名称const componentName ref(account)// 点击…

【算法】一类支持向量机OC-SVM(1)

【算法】一类支持向量机OC-SVM 前言一类支持向量机OC-SVM 概念介绍示例编写数据集创建实现一类支持向量机OC-SVM完整的示例输出 前言 由于之前毕设期间主要的工具就是支持向量机&#xff0c;从基础的回归和分类到后来的优化&#xff0c;在接触到支持向量机还有一类支持向量机的…

unity

Unity官方下载_Unity最新版_从Unity Hub下载安装 | Unity中国官网 Unity Remote - Unity 手册 登陆账号&#xff0c;找到一个3d 免费资源 3D Animations & Models | Unity Asset Store unity 里面window->package Manager 里面可以看到自己的asset &#xff0c;下载后…

Java SE入门及基础(43)

目录 File类 1. File类的作用 2. File类的使用 常用构造方法 示例 常用方法 1.获取文件相关信息 示例 2.文件相关的判断 示例 3.文件列表相关 示例 3. 递归 示例 1.使用递归求1~100的累加和。 2.使用递归打印文件夹下所有文件信息 练习 思考&#xff1a;如何删…

《Effective Modern C++》- 极精简版 36-42条

本文章属于专栏《业界Cpp进阶建议整理》 继续上篇《Effective Modern C》- 极精简版 30-35条。 本文列出《Effective Modern C》的36-42条的个人理解的极精简版本。 Item36、如果有异步的&#xff0c;请指定std::launch::async demo代码为&#xff1a; int calculateSum(int a…

MySQL 数据库压力测试

文章目录 前言1. 安装部署1.1 二进制安装1.2 源码安装 2. 服务器性能测试2.1 CPU2.2 内存2.3 磁盘 3. MySQL 基准测试3.1 参数解析3.2 压测命令3.3 输出解读3.4 结果分析 前言 Sysbench 是一个开源的多线程基准测试工具&#xff0c;也是目前使用最多的 MySQL 压力测试工具。本…

树莓派与电脑视频实时传输实现

编程环境 1、 树莓派 4B 2、 windows 编程语言 python 应用 tkinter scoket opencv 效果 视频同传 服务端视频初始化 服务端视频读取 windows 客户端接收视频流&#xff0c;队列存储 解析视频&#xff0c;存入队列 ui页面数据刷新 下载链接&#xff1a;https://…

什么是虚假唤醒?为什么会产生虚假唤醒?

什么是虚假唤醒&#xff1f; 当一定的条件触发时会唤醒很多在阻塞态的线程&#xff0c;但只有部分的线程唤醒是有用的&#xff0c;其余线程的唤醒是多余的。 比如说卖货&#xff0c;如果本来没有货物&#xff0c;突然进了一件货物&#xff0c;这时所有的顾客都被通知了&#x…

1178: 密码翻译(python)

题目描述 在情报传递过程中&#xff0c;为了防止情报被截获&#xff0c;往往需要对情报用一定的方式加密&#xff0c;简单的加密算法虽然不足以完全避免情报被破译&#xff0c;但仍然能防止情报被轻易的识别。我们给出一种最简的的加密方法&#xff0c;对给定的一个字符串&…

elasticsearch篇:数据聚合

1.数据聚合 聚合&#xff08;aggregations&#xff09;可以让我们极其方便的实现对数据的统计、分析、运算。例如&#xff1a; 什么品牌的手机最受欢迎&#xff1f; 这些手机的平均价格、最高价格、最低价格&#xff1f; 这些手机每月的销售情况如何&#xff1f; 实现这些…

VUE3项目学习系列--Axios二次封装(五)

Axios中文文档 | Axios中文网 (axios-http.cn) Axios 是一个基于 promise 网络请求库&#xff0c;作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequ…

【洛谷 P8637】[蓝桥杯 2016 省 B] 交换瓶子 题解(贪心算法)

[蓝桥杯 2016 省 B] 交换瓶子 题目描述 有 N N N 个瓶子&#xff0c;编号 1 ∼ N 1 \sim N 1∼N&#xff0c;放在架子上。 比如有 5 5 5 个瓶子&#xff1a; 2 , 1 , 3 , 5 , 4 2,1,3,5,4 2,1,3,5,4 要求每次拿起 2 2 2 个瓶子&#xff0c;交换它们的位置。 经过若干次…

解释器模式(Interpreter Pattern)

解释器模式 说明 解释器模式&#xff08;Interpreter Pattern&#xff09;属于行为型模式&#xff0c;是指给定一门语言&#xff0c;定义它的语法&#xff08;文法&#xff09;的一种表示&#xff0c;并定义一个解释器&#xff0c;该解释器使用该表示来解释语言中的句子。是一…