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

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



WSGIServer <– HTTPServer <– SocketServer.TCPServer <– TCPServer <– BaseServer

request: WSGIRequest <– django.http.HttpRequest
response: HttpResponse

第一步 启动django server: python runserver
os.environ[“DJANGO_SETTINGS_MODULE”] = “settings”
from import execute_from_command_line
run() - django/core/management/commands/
1. handler = self.get_handler(*args, **options)
1) get_handler()
2) get_internal_wsgi_application() - django/core/servers/
from django.conf import settings
3) return WSGIHandler() - django/core/
2. run(self.addr, int(self.port), handler, ipv6=self.use_ipv6, threading=threading)
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.process_request(request, client_address)
1) t = threading.Thread(target = self.process_request_thread, args = (request, client_address))

# 新建了一个线程去处理 request.

self.finish_request(request, client_address)
线程调用finish_request # call WSGIHandler:
BaseServer –> finish_request() –> self.RequestHandlerClass(request, client_address, self)
# python2.7/
BaseRequestHandler –> self.handle() # python2.7/
WSGIRequestHandler –>
# 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.

调用 WSGIHandler的整个过程:
调用 WSGIHandler(base.BaseHandler)的 __call__ 方法 - (django/core/
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.
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)
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
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