0%

Django 阅读源码笔记 - Hypers 第一周

来 Hypers 上班的第一周, 在看 Django 的 middleware 的时候, 对 process request, view, template 和 response的四个过程有些疑惑, 俊哥建议我读一下 django 的源码.
在这篇日志中, 我整理了 django 从 启动 server --> 处理 Request --> 返回 response 的整个 代码流程.

自己做的有道云笔记的链接: http://note.youdao.com/noteshare?id=465ac1f8ca5a82a9cb998d49bb763df8


Reference:
基础的一些类:
WSGIServer <-- HTTPServer <-- SocketServer.TCPServer <-- TCPServer <-- BaseServer
request: WSGIRequest <-- django.http.HttpRequest
response: HttpResponse
第一步 启动 django server: python manage.py runserver
os.environ["DJANGO_SETTINGS_MODULE"] = "settings"
from django.core.management import execute_from_command_line
execute_from_command_line(sys.argv)
run() - django/core/management/commands/runserver.py
inner_run()
1. handler = self.get_handler(*args, **options)
WSGIHandler:
1) get_handler()
2) get_internal_wsgi_application() - django/core/servers/basehttp.py
from django.conf import settings
3) return WSGIHandler() - django/core/wsgi.py
2. run(self.addr, int(self.port), handler, ipv6=self.use_ipv6, threading=threading)
WSGIServer:
django/core/servers/basehttp.py
1) run(self.addr, int(self.port), handler, ipv6=self.use_ipv6, threading=threading)
httpd_cls --> 获得一个 WSGIServer 类型
httpd = httpd_cls(server_address, WSGIRequestHandler, ipv6=ipv6) --> WSGIServer
2) httpd.serve_forever() # while 循环接收 Request 请求
select model
获得 r, w, e --> read, write, error 描述符 --> [], [], []
当 WSGIServer (serve_forever) 接收到 Request:
r, w, e = [<django.core.servers.basehttp.WSGIServer object], [], []
if self in r:
self._handle_request_noblock()
self.process_request(request, client_address)
1) t = threading.Thread(target = self.process_request_thread, args = (request, client_address))
# 新建了一个 线程 去处理 request.
process_request_thread()
self.finish_request(request, client_address)
线程 调用 finish_request # call WSGIHandler:
BaseServer --> finish_request() --> self.RequestHandlerClass(request, client_address, self)
# python2.7/SocketServer.py
BaseRequestHandler --> self.handle() # python2.7/SocketServer.py
WSGIRequestHandler --> handler.run(self.server.get_app())
# self.server: WSGIServer; handler: ServerHandler; self.server.get_app(): StaticFilesHandler
BaseHandler --> self.result = application(self.environ, self.start_response)
# application: StaticFilesHandler
StaticFilesHandler(WSGIHandler) --> return self.application(environ, start_response)
# Explicitly shutdown. socket.close() merely releases the socket and waits for GC to perform the actual close.
self.shutdown_request(request)
调用 WSGIHandler的整个过程:
调用 WSGIHandler(base.BaseHandler)的 call 方法 - (django/core/wsgi.py)
Step 1:
1). self.load_middleware() -> Populate middleware lists from settings
2). signals.request_started.send(...) -> fires the dispatcher signal request_started
3). request = self.request_class(environ) -> 实例 WSGIRequest(http.HttpRequest)
4). response = self.get_response(request) -> Step2
Returns an HttpResponse object for the given HttpRequest
Step 2: Request Middleware
the middleware methods applied here simply do some processing and decide whether to add, remove or supplement attributes of the request.
python</div></blockquote></blockquote></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px;"><blockquote style="margin:0 0 0 40px;border:none;padding:0px;"><blockquote style="margin:0 0 0 40px;border:none;padding:0px;"><div style="white-space: pre-wrap;line-height:1.5;text-align:left;line-height:1.5;" yne-bulb-block="paragraph"> for middleware_method in self._request_middleware:</div></blockquote></blockquote></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px;"><blockquote style="margin:0 0 0 40px;border:none;padding:0px;"><blockquote style="margin:0 0 0 40px;border:none;padding:0px;"><div style="white-space: pre-wrap;line-height:1.5;text-align:left;line-height:1.5;" yne-bulb-block="paragraph"> response = middleware_method(request)</div></blockquote></blockquote></blockquote><blockquote style="margin:0 0 0 40px;border:none;padding:0px;"><blockquote style="margin:0 0 0 40px;border:none;padding:0px;"><blockquote style="margin:0 0 0 40px;border:none;padding:0px;"><div style="white-space: pre-wrap;line-height:1.5;text-align:left;line-height:1.5;" yne-bulb-block="paragraph">
Step 3: 用 RegexURLResolver 处理 requested URL
生成了一个 URL resolver, 在指定的 url.py 里根据 regex 遍历找到对应的 view.
option1: 如果是 include 的话, 继续找
option2: 找到了的话返回这三个东西:
1. matched item
2. a list of non-named matched groups from the URL (to be used as positional arguments for the view)
3. kwargs. eg. {'template_name': 'registration/login.html'}
callback, callback_args, callback_kwargs = resolver_match
这三个 View 的参数: 1. view 的 reference 2. args 3. kwargs
Step 4: Apply view middleware (类似 Request Middleware)
for middleware_method in self._view_middleware:
response = middleware_method(request, callback, callback_args, callback_kwargs)
view 的三个条件:
1) 必须可以被调用的.
2) 输入: 第一个 positional 参数必须为 django.http.HttpRequest.
3) 输出: 返回必须为一个 django.http.HttpResponse OR raise 一个异常.
Step 5: Exception Middleware
如果在 view 的执行中遇到异常, 就会执行_exception_middleware list 里的 所有 instance.
Step 6: Template Response
如果 response 有 render 属性的话:
1. 调用 template 的 response middleware
2. Render response: 返回 TemplateResponse,
content = template.render(context, self._request)
>>> context = Context({"my_name": "Dolores"})
>>> template.render(context)
"My name is Dolores."
Step 7: Apply response middleware, regardless of the response
Step 8:
(执行完 handler 的 get_response 方法)
对 Response 设 header, cache, etc.
生成一个 HttpResponse, 它的两个参数:
1. content: 一般是 TemplateResponse 的 content (render 生成的 HTML 代码).
2. mime_type: A value for the Content-Type header of the response. --> response_headers