[Django 0-1] Core.Handlers 模块

2024-03-16 05:04
文章标签 模块 django core handlers

本文主要是介绍[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 提供异步处理能力。很好的实现了请求的处理流程,并提供了中间件的功能。

这篇关于[Django 0-1] Core.Handlers 模块的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/814362

相关文章

Python使用date模块进行日期处理的终极指南

《Python使用date模块进行日期处理的终极指南》在处理与时间相关的数据时,Python的date模块是开发者最趁手的工具之一,本文将用通俗的语言,结合真实案例,带您掌握date模块的六大核心功能... 目录引言一、date模块的核心功能1.1 日期表示1.2 日期计算1.3 日期比较二、六大常用方法详

Django序列化中SerializerMethodField的使用详解

《Django序列化中SerializerMethodField的使用详解》:本文主要介绍Django序列化中SerializerMethodField的使用,具有很好的参考价值,希望对大家有所帮... 目录SerializerMethodField的基本概念使用SerializerMethodField的

python中time模块的常用方法及应用详解

《python中time模块的常用方法及应用详解》在Python开发中,时间处理是绕不开的刚需场景,从性能计时到定时任务,从日志记录到数据同步,时间模块始终是开发者最得力的工具之一,本文将通过真实案例... 目录一、时间基石:time.time()典型场景:程序性能分析进阶技巧:结合上下文管理器实现自动计时

Node.js net模块的使用示例

《Node.jsnet模块的使用示例》本文主要介绍了Node.jsnet模块的使用示例,net模块支持TCP通信,处理TCP连接和数据传输,具有一定的参考价值,感兴趣的可以了解一下... 目录简介引入 net 模块核心概念TCP (传输控制协议)Socket服务器TCP 服务器创建基本服务器服务器配置选项服

Python利用自带模块实现屏幕像素高效操作

《Python利用自带模块实现屏幕像素高效操作》这篇文章主要为大家详细介绍了Python如何利用自带模块实现屏幕像素高效操作,文中的示例代码讲解详,感兴趣的小伙伴可以跟随小编一起学习一下... 目录1、获取屏幕放缩比例2、获取屏幕指定坐标处像素颜色3、一个简单的使用案例4、总结1、获取屏幕放缩比例from

nginx-rtmp-module模块实现视频点播的示例代码

《nginx-rtmp-module模块实现视频点播的示例代码》本文主要介绍了nginx-rtmp-module模块实现视频点播,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习... 目录预置条件Nginx点播基本配置点播远程文件指定多个播放位置参考预置条件配置点播服务器 192.

多模块的springboot项目发布指定模块的脚本方式

《多模块的springboot项目发布指定模块的脚本方式》该文章主要介绍了如何在多模块的SpringBoot项目中发布指定模块的脚本,作者原先的脚本会清理并编译所有模块,导致发布时间过长,通过简化脚本... 目录多模块的springboot项目发布指定模块的脚本1、不计成本地全部发布2、指定模块发布总结多模

如何使用celery进行异步处理和定时任务(django)

《如何使用celery进行异步处理和定时任务(django)》文章介绍了Celery的基本概念、安装方法、如何使用Celery进行异步任务处理以及如何设置定时任务,通过Celery,可以在Web应用中... 目录一、celery的作用二、安装celery三、使用celery 异步执行任务四、使用celery

Python中构建终端应用界面利器Blessed模块的使用

《Python中构建终端应用界面利器Blessed模块的使用》Blessed库作为一个轻量级且功能强大的解决方案,开始在开发者中赢得口碑,今天,我们就一起来探索一下它是如何让终端UI开发变得轻松而高... 目录一、安装与配置:简单、快速、无障碍二、基本功能:从彩色文本到动态交互1. 显示基本内容2. 创建链

Node.js 中 http 模块的深度剖析与实战应用小结

《Node.js中http模块的深度剖析与实战应用小结》本文详细介绍了Node.js中的http模块,从创建HTTP服务器、处理请求与响应,到获取请求参数,每个环节都通过代码示例进行解析,旨在帮... 目录Node.js 中 http 模块的深度剖析与实战应用一、引言二、创建 HTTP 服务器:基石搭建(一