django 3.2.13
本文只算是本人片面之言(当然也会借鉴网络上公开资料),而且技术含量比较低,内容质量也一般,大家仅限参考即可
如果对本文看不太懂,请先阅读后面文章,等都差不多看完再回顾来看
命令行结论:其在第二步utility.execute()函数会根据命令行参数,分发给不同的类进行处理
def main():
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'testDjango.settings')
try:
from django.core.management import execute_from_command_line
except ImportError as exc:
---
execute_from_command_line(sys.argv)
python manage.py runserver、python manage.py helpdef execute_from_command_line(argv=None):
utility = ManagementUtility(argv)
utility.execute()
def execute(self):
---
if subcommand == 'help':
---
elif subcommand == 'version' or self.argv[1:] == ['--version']:
sys.stdout.write(django.get_version() + '\n')
elif self.argv[1:] in (['--help'], ['-h']):
sys.stdout.write(self.main_help_text() + '\n')
else:
self.fetch_command(subcommand).run_from_argv(self.argv)
def run_from_argv(self, argv):
self._called_from_command_line = True
parser = self.create_parser(argv[0], argv[1])
options = parser.parse_args(argv[2:])
cmd_options = vars(options)
args = cmd_options.pop('args', ())
handle_default_options(options)
try:
self.execute(*args, **cmd_options)
except CommandError as e:
---
super().execute(*args, **options) #继承下来父类 def handle(self, *args, **options):
if not settings.DEBUG and not settings.ALLOWED_HOSTS:
raise CommandError('You must set settings.ALLOWED_HOSTS if DEBUG is False.')
self.use_ipv6 = options['use_ipv6']
if self.use_ipv6 and not socket.has_ipv6:
raise CommandError('Your Python does not support IPv6.')
self._raw_ipv6 = False
if not options['addrport']:
---
else:
---
if not self.addr:
self.addr = self.default_addr_ipv6 if self.use_ipv6 else self.default_addr
self._raw_ipv6 = self.use_ipv6
self.run(**options)
def run(self, **options):
use_reloader = options['use_reloader']
if use_reloader:
autoreload.run_with_reloader(self.inner_run, **options)
else:
self.inner_run(None, **options)
def inner_run(self, *args, \*\*options)再执行run函数 def inner_run(self, *args, **options):
---
try:
handler = self.get_handler(*args, **options)
run(self.addr, int(self.port), handler,
ipv6=self.use_ipv6, threading=threading, server_cls=self.server_cls)
except OSError as e:
---
httpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {}) 这一步特别重要,其涉及到较长的继承关系,2.监听-4.1这一环节会介绍到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:
httpd.daemon_threads = True
httpd.set_app(wsgi_handler)
httpd.serve_forever()
总结流程:
解释:WSGI开启后,不间断的监听外界的请求
快速阅读:下面写的比较麻烦,最快了解监听和到中间件前的经过就是去读 1 、12.1 和 13
httpd.serve_forever(),其使得进入监听即一个死循环def run(addr, port, wsgi_handler, ipv6=False, threading=False, server_cls=WSGIServer):
---
httpd.set_app(wsgi_handler)
httpd.serve_forever()
serve_forever()函数里面执行,当ready有值时,表示有请求发来,然后进入self._handle_request_noblock() def serve_forever(self, poll_interval=0.5):
self.__is_shut_down.clear()
try:
with _ServerSelector() as selector:
selector.register(self, selectors.EVENT_READ)
while not self.__shutdown_request:
ready = selector.select(poll_interval)
if self.__shutdown_request:
break
if ready:
self._handle_request_noblock()
self.service_actions()
---
self._handle_request_noblock()正常请求将进入self.process_request(request, client_address) def _handle_request_noblock(self):
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)
self.process_request(request, client_address)进入来到了ThreadingMixIn.process_requesthttpd_cls = type('WSGIServer', (socketserver.ThreadingMixIn, server_cls), {})ThreadingMixIn.process_request def process_request(self, request, client_address):
"""Start a new thread to process the request."""
t = threading.Thread(target = self.process_request_thread,
args = (request, client_address))
t.daemon = self.daemon_threads
if not t.daemon and self.block_on_close:
if self._threads is None:
self._threads = []
self._threads.append(t)
t.start()
def process_request(self, request, client_address)里面的t = threading.Thread(target = self.process_request_thread,args = (request, client_address))实际调用了self.process_request_thread,但是等t.start()才会真正执行 def process_request_thread(self, request, client_address):
"""Same as in BaseServer but as a thread.
In addition, exception handling is done here.
"""
try:
self.finish_request(request, client_address)
except Exception:
self.handle_error(request, client_address)
finally:
self.shutdown_request(request)
def process_request_thread(self, request, client_address)进入,self.finish_request(request, client_address),继续完成请求self.RequestHandlerClass不是已经有的类,而是初始化的时候赋值,其值变为了某个类httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6),此时的httpd_cls是type动态创建的,继承了ThreadingMixIn和server_cls对应得WSGIServer,实例化时会执行def __init__方法,其关键执行了self.RequestHandlerClass = RequestHandlerClassclass BaseServer:
timeout = None
def __init__(self, server_address, RequestHandlerClass):
"""Constructor. May be extended, do not override."""
self.server_address = server_address
self.RequestHandlerClass = RequestHandlerClass
self.__is_shut_down = threading.Event()
self.__shutdown_request = False
def finish_request(self, request, client_address):
self.RequestHandlerClass(request, client_address, self)
# self.RequestHandlerClass等同于self.WSGIRequestHandler
self.RequestHandlerClass(request, client_address, self),即去WSGIRequestHandler类里面初始化,根据一层层继承关系,只要最老类BaseRequestHandler有初始化方法class 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()
def __init__(self, request, client_address, server):进入self.handle()self.handle(),根据继承关系,其就在最小子类WSGIRequestHandler里面 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 (AttributeError, OSError):
pass
def handle(self)进入self.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())
def handle_one_request(self)进入handler.run(self.server.get_app())handler.run(self.server.get_app())执行了self.server.get_app(),其返回django.contrib.staticfiles.handlers.StaticFilesHandler,handler.run把其当参数传递了过去 def run(self, application):
try:
self.setup_environ()
self.result = application(self.environ, self.start_response)
self.finish_response()
except (ConnectionAbortedError, BrokenPipeError, ConnectionResetError):
return
except:
---
def run(self, application)进入self.result = application(self.environ, self.start_response),其中application是django.contrib.staticfiles.handlers.StaticFilesHandlerclass StaticFilesHandler(StaticFilesHandlerMixin, WSGIHandler):
def __init__(self, application):
self.application = application
self.base_url = urlparse(self.get_base_url())
super().__init__()
def __call__(self, environ, start_response):
if not self._should_handle(get_path_info(environ)):
return self.application(environ, start_response)
return super().__call__(environ, start_response)
def __call__(self, environ, start_response)方法,进入return self.application(environ, start_response),此时self.application已经初始化了是WSGIHandlerrequest = self.request_class(environ)获取到用户请求的url后面就开始配置runserver启动时候加载的url; response = self.get_response(request)获取用户url对应的响应准备开始往视图转 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 = self.get_response(request),结束,再下一步就要开始中间件的进行 def get_response(self, request):
set_urlconf(settings.ROOT_URLCONF)
response = self._middleware_chain(request)
response._resource_closers.append(request.close)
if response.status_code >= 400:
log_response(
'%s: %s', response.reason_phrase, request.path,
response=response,
request=request,
)
return response
解释:中间件的执行需要联系着上面运行过程,这个过程是一个递归的过程,下面介绍的五个函数是中间件命名规则对应得内容
process_request()和process_response() @wraps(get_response)
def inner(request):
try:
response = get_response(request) # 此进入循环
except Exception as exc:
response = response_for_exception(request, exc)
return response
return inner
def __call__(self, request):
# Exit out to async mode, if needed
if asyncio.iscoroutinefunction(self.get_response):
return self.__acall__(request)
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request) # 进行中间件的process_request步骤
response = response or self.get_response(request) # 此进入循环
if hasattr(self, 'process_response'):
response = self.process_response(request, response) # 此是递归后执行的
return response
process_view()、process_template_response()和process_exception()进入视图的关键函数:
callback, callback_args, callback_kwargs = self.resolve_request(request) # callback即对于视图函数url匹配到对应的view函数for middleware_method in self._view_middleware_view_middleware里面放着所有的process_view()函数(初始化时加载的), process_view()正是在该代码下面的环节循环执行response = wrapped_callback(request, *callback_args, **callback_kwargs) 回调函数传参,并返回试图函数响应。
response = self.process_exception_by_middleware(e, request)对应process_exception()self._template_response_middleware 循环加载模板中间件 def _get_response(self, request):
response = None
callback, callback_args, callback_kwargs = self.resolve_request(request)
for middleware_method in self._view_middleware:
response = middleware_method(request, callback, callback_args, callback_kwargs)
if response:
break
if response is None:
wrapped_callback = self.make_view_atomic(callback) # 找到视图函数
# If it is an asynchronous view, run it in a subthread.
if asyncio.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
self.check_response(response, callback)
if hasattr(response, 'render') and callable(response.render):
for middleware_method in self._template_response_middleware:
response = middleware_method(request, response)
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:
raise
return response
@wraps(get_response)
def inner(request):
try:
response = get_response(request) # 此进入循环
except Exception as exc:
response = response_for_exception(request, exc)
return response
return inner
def __call__(self, request):
# Exit out to async mode, if needed
if asyncio.iscoroutinefunction(self.get_response):
return self.__acall__(request)
response = None
if hasattr(self, 'process_request'):
response = self.process_request(request)
response = response or self.get_response(request) # 此进入循环
if hasattr(self, 'process_response'):
response = self.process_response(request, response) # 进行中间件的process_response步骤
return response