django 处理请求
本文基于 django runsever
- 入口
- 执行 python manage.py runserver
- 调用 django.core.management.commands.runserver.Command.handle
- 文件 runserver.py(django/core/management/commands/runserver.py)
- 执行 python manage.py runserver
- 启动 TCP server
- 从上面 handle 会进入 django.core.servers.basehttp.run
# 其中 server_cls 为 WSGIServer
def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
server_address = (addr, port)
if threading:
httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {})
else:
httpd_cls = server_cls
httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6)
if threading:
# ThreadingMixIn.daemon_threads indicates how threads will behave on an
# abrupt shutdown; like quitting the server by the user or restarting
# by the auto-reloader. True means the server will not wait for thread
# termination before it quits. This will make auto-reloader faster
# and will prevent the need to kill the server manually if a thread
# isn't terminating correctly.
httpd.daemon_threads = True
# wsgi_handler 为 settings.WSGI_APPLICATION 一般为 product_name/wsgi.py 中的 application
httpd.set_app(wsgi_handler) # httpd_cls.application = application 在后面 get_app 方法中会获取到
httpd.serve_forever()
- 进入 server_forever
# socketserver.BaseServer.serve_forever
def serve_forever(self, poll_interval=0.5):
"""Handle one request at a time until shutdown.
Polls for shutdown every poll_interval seconds. Ignores
self.timeout. If you need to do periodic tasks, do them in
another thread.
"""
self.__is_shut_down.clear()
try:
# XXX: Consider using another file descriptor or connecting to the
# socket to wake this up instead of polling. Polling reduces our
# responsiveness to a shutdown request and wastes cpu at all other
# times.
with _ServerSelector() as selector:
selector.register(self, selectors.EVENT_READ)
while not self.__shutdown_request:
ready = selector.select(poll_interval)
# bpo-35017: shutdown() called during select(), exit immediately.
if self.__shutdown_request:
break
if ready:
self._handle_request_noblock()
self.service_actions()
finally:
self.__shutdown_request = False
self.__is_shut_down.set()
- 接下来进入 self._handle_request_noblock()
# socketserver.BaseServer._handle_request_noblock
def _handle_request_noblock(self):
"""Handle one request, without blocking.
I assume that selector.select() has returned that the socket is
readable before this function was called, so there should be no risk of
blocking in get_request().
"""
try:
request, client_address = self.get_request()
except OSError:
return
if self.verify_request(request, client_address):
try:
self.process_request(request, client_address)
except Exception:
self.handle_error(request, client_address)
self.shutdown_request(request)
except:
self.shutdown_request(request)
raise
else:
self.shutdown_request(request)
其中 request, client_address = self.get_request(), 这时候 request 还只是一个 socket 对象
# socketserver.TCPServer.get_request
def get_request(self):
"""Get the request and client address from the socket.
May be overridden.
"""
return self.socket.accept()
- 处理请求 self.process_request(request, client_address)
# socketserver.BaseServer.process_request
def process_request(self, request, client_address):
"""Call finish_request.
Overridden by ForkingMixIn and ThreadingMixIn.
"""
self.finish_request(request, client_address)
self.shutdown_request(request)
- 完成一个 request self.finish_request(request, client_address)
# socketserver.BaseServer.finish_request
def finish_request(self, request, client_address):
"""Finish one request by instantiating RequestHandlerClass."""
self.RequestHandlerClass(request, client_address, self)
其中 RequestHandlerClass 为 WSGIRequestHandler (django.core.servers.basehttp.WSGIRequestHandler)
注意: 这时候 request 还只是一个 socket 对象 <class 'socket.socket'>
- 实例化 handler socketserver.BaseRequestHandler
# socketserver.BaseRequestHandler
def __init__(self, request, client_address, server):
self.request = request
self.client_address = client_address
self.server = server
self.setup()
try:
self.handle()
finally:
self.finish()
其中 self.handle
# django.core.servers.basehttp.WSGIRequestHandler.handle
def handle(self):
self.close_connection = True
self.handle_one_request()
while not self.close_connection:
self.handle_one_request()
try:
self.connection.shutdown(socket.SHUT_WR)
except (socket.error, AttributeError):
pass
- 从请求中获取信息 self.handle_one_request()
# django.core.servers.basehttp.WSGIRequestHandler.handle_one_request
def handle_one_request(self):
"""Copy of WSGIRequestHandler.handle() but with different ServerHandler"""
self.raw_requestline = self.rfile.readline(65537)
if len(self.raw_requestline) > 65536:
self.requestline = ''
self.request_version = ''
self.command = ''
self.send_error(414)
return
if not self.parse_request(): # An error code has been sent, just exit
return
handler = ServerHandler(
self.rfile, self.wfile, self.get_stderr(), self.get_environ()
)
handler.request_handler = self # backpointer for logging & connection closing
handler.run(self.server.get_app()) # 对应上面的 set_app
其中 ServerHandler 实例化中没有做特殊的操作
# django.core.servers.basehttp.ServerHandler
pass
run
# wsgiref.handlers.BaseHandler.run
# application 则是上面的 get_app 拿到的结果
def run(self, application):
"""Invoke the application"""
# Note to self: don't move the close()! Asynchronous servers shouldn't
# call close() from finish_response(), so if you close() anywhere but
# the double-error branch here, you'll break asynchronous servers by
# prematurely closing. Async servers must return from 'run()' without
# closing if there might still be output to iterate over.
try:
self.setup_environ()
self.result = application(self.environ, self.start_response)
self.finish_response()
except:
try:
self.handle_error()
except:
# If we get an error handling an error, just give up already!
self.close()
raise # ...and let the actual server figure it out.
调用 handler 的 __call__
- 上面的 application 其实就是 product/wsgi.py 中的 application 最终拿到的是 WSGIHandler 的一个实例
# django.core.handlers.wsgi.WSGIHandler
class WSGIHandler(base.BaseHandler):
request_class = WSGIRequest
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.load_middleware()
def __call__(self, environ, start_response):
set_script_prefix(get_script_name(environ))
signals.request_started.send(sender=self.__class__, environ=environ) # 发送 request_started 信号
request = self.request_class(environ) # 实例化 WSGIRequest 得到 django 中 view 中真实的 request
response = self.get_response(request) # 获取 response 会进入 middleware
response._handler_class = self.__class__
status = '%d %s' % (response.status_code, response.reason_phrase)
response_headers = list(response.items())
for c in response.cookies.values():
response_headers.append(('Set-Cookie', c.output(header='')))
start_response(status, response_headers)
if getattr(response, 'file_to_stream', None) is not None and environ.get('wsgi.file_wrapper'):
response = environ['wsgi.file_wrapper'](response.file_to_stream)
return response
- 实例化 Request
# django.core.handlers.wsgi.WSGIRequest
pass
- 获取 response
# django.core.handlers.base.BaseHandler.get_response
def get_response(self, request):
"""Return an HttpResponse object for the given HttpRequest."""
# Setup default url resolver for this thread
set_urlconf(settings.ROOT_URLCONF)
response = self._middleware_chain(request)
response._closable_objects.append(request)
# If the exception handler returns a TemplateResponse that has not
# been rendered, force it to be rendered.
if not getattr(response, 'is_rendered', True) and callable(getattr(response, 'render', None)):
response = response.render()
if response.status_code >= 400:
log_response(
'%s: %s', response.reason_phrase, request.path,
response=response,
request=request,
)
return response
接着回到 run
- 关注下 self.finish_response()
# wsgiref.handlers.BaseHandler.finish_response
def finish_response(self):
"""Send any iterable data, then close self and the iterable
Subclasses intended for use in asynchronous servers will
want to redefine this method, such that it sets up callbacks
in the event loop to iterate over the data, and to call
'self.close()' once the response is finished.
"""
try:
if not self.result_is_file() or not self.sendfile():
for data in self.result:
self.write(data)
self.finish_content()
finally:
self.close()
# 其中 self.write
# wsgiref.handlers.BaseHandler.write
def write(self, data):
"""'write()' callable as specified by PEP 3333"""
assert type(data) is bytes, \
"write() argument must be a bytes instance"
if not self.status:
raise AssertionError("write() before start_response()")
elif not self.headers_sent:
# Before the first output, send the stored headers
self.bytes_sent = len(data) # make sure we know content-length
self.send_headers()
else:
self.bytes_sent += len(data)
# XXX check Content-Length and truncate if too many bytes written?
self._write(data)
self._flush()
# 其中 self._write
# wsgiref.handlers.SimpleHandler._write
def _write(self,data):
result = self.stdout.write(data)
if result is None or result == len(data):
return
from warnings import warn
warn("SimpleHandler.stdout.write() should not do partial writes",
DeprecationWarning)
while True:
data = data[result:]
if not data:
break
result = self.stdout.write(data)
# 其中 result = self.stdout.write(data)
def write(self, b):
self._sock.sendall(b)
with memoryview(b) as view:
return view.nbytes
django 处理请求的更多相关文章
- Django中请求的生命周期
1. 概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串. 在Django中,当我们访问一个的url时,会通过路由匹配进入相应的html网页中. Django的请求生命周期是指当用户 ...
- django 前端请求跨域问题解决
django 前端请求跨域问题解决 笔者之前在做django-restful-api开发的时候,在前端请求页面发送请求的时候直接出现301,域名重定向的问题,经过一番查阅资料,终于得到了非常完美的解决 ...
- Django的请求生命周期
Django的请求生命周期 请求生命周期 请求生命周期是指当用户在浏览器上输入url到用户看到网页的这个时间段内,Django后台所发生的事情. 1.客户端发送Http请求 2 .服务器接收,根据请求 ...
- Django 框架 django的请求生命周期
概述 首先我们知道HTTP请求及服务端响应中传输的所有数据都是字符串,同时http请求是无状态的,可以通过session和cookie来辅助. 浏览器通过ip和端口及路由方式访问服务端. 在Djang ...
- django从请求到返回都经历了什么[转]
原文地址:http://projectsedu.com/2016/10/17/django从请求到返回都经历了什么/ 从runserver说起 ruserver是使用django自己的web serv ...
- [oldboy-django][2深入django]django一个请求的生命周期 + WSGI + 中间件
1 WSGI # WSGI(是一套协议,很多东西比如wsgiref, uwsgiref遵循这一套协议) - django系统本质 别人的socket(wsgiref或者uwsgiref) + djan ...
- DRF框架(一)——restful接口规范、基于规范下使用原生django接口查询和增加、原生Django CBV请求生命周期源码分析、drf请求生命周期源码分析、请求模块request、渲染模块render
DRF框架 全称:django-rest framework 知识点 1.接口:什么是接口.restful接口规范 2.CBV生命周期源码 - 基于restful规范下的CBV接口 3.请求组件 ...
- Django - 获取请求方式
//获取请过来得得请求类型 method = request.method 通过Django 的form 判断用户输入是否通过验证 check = forms.LoginFrom(request.PO ...
- [原]Django慢请求分析工具--dogslow
当你的网站突然变慢了,你怎么办? 先看监控,查看系统的资源消耗,CPU?IO?磁盘? 然后看日志,查看第一个出现慢请求的接口是哪个? 然后看依赖的服务,是第三方服务还是DB瓶颈,还是redis变慢,还 ...
- django HTTP请求(Request)和回应(Response)对象
Django使用request和response对象在系统间传递状态.—(阿伦)当一个页面被请示时,Django创建一个包含请求元数据的 HttpRequest 对象. 然后Django调入合适的视图 ...
随机推荐
- HDU - 1711:Number Sequence (KMP模板)
原题链接 KMP模板:AC,858ms,13112KB内存 消耗太大了 #include<bits/stdc++.h> using namespace std; using namespa ...
- JXUST_NC - ACM工作室20级选拔赛题解
A - RioTian学长的星际航线 并查集板子 #include <bits/stdc++.h> using namespace std; const int maxn = 1010; ...
- 13、SpringBoot-配置文件里密码加密
系列导航 springBoot项目打jar包 1.springboot工程新建(单模块) 2.springboot创建多模块工程 3.springboot连接数据库 4.SpringBoot连接数据库 ...
- 五、java操作swift对象存储(官网样例)
系列导航 一.swift对象存储环境搭建 二.swift添加存储策略 三.swift大对象--动态大对象 四.swift大对象--静态态大对象 五.java操作swift对象存储(官网样例) 六.ja ...
- 8 Englishi 词根
测一测 physical obesity skinny sliny stout skeleton external appearance recede unprecededented feinge e ...
- Python实现PowerPoint(PPT/PPTX)到PDF的批量转换
如果需要处理大量的PPT转PDF的工作,一个个打开并另存为PDF是非常费时的做法.我们可以利用Python编程语言的强大的工具来自动化这个过程,使得批量转换变得简单而高效.本文将介绍如何使用Pytho ...
- Redis6常用语句
格式:(待补充) /redis-6.2.4/src/redis-cli -h $ip -p $port -a $password [command] #以下ip/port/password根据实际情况 ...
- 概率图模型 · 蒙特卡洛采样 · MCMC | 非常好的教学视频
https://www.bilibili.com/video/BV17D4y1o7J2?p=1 非常感谢!感觉学会一点了,应该能写作业了
- 两个List< string>比较是否相同的N种方法,你用过哪种?
今天在一技术群看一群大佬讨论: 有没有优雅的写法,比较两个List集合中的元素是不是完全一致... 站长最近也无聊,通过群里的聊天记录和给出的参考链接,简单做做总结,万一后面大家能用上呢? 我们做简单 ...
- 为什么 sort() 中的 return a-b 可以决定升序
arr.sort( function(a,b){ return a-b; } ) 千万不要理解成 a 减 b 其实它代表的是26个字母中的 a 和 b b 比 a 大,所以 a - b 就是升序,写成 ...