Just relax, take it easy..

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
for middleware_method in self._request_middleware:
response = middleware_method(request)
```
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