一、項目初始化的核心模塊分析:
get_internal_wsgi_application源碼:
def get_internal_wsgi_application():
from django.conf import settings
app_path = getattr(settings, 'WSGI_APPLICATION')
if app_path is None:
return get_wsgi_application() (返回一個WSGIHandler實例)
...
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 = self.request_class(environ)
response = self.get_response(request)
response._handler_class = self.__class__
status = '%d %s' % (response.status_code, response.reason_phrase)
response_headers = [
*response.items(),
*(('Set-Cookie', c.output(header='')) for c in response.cookies.values()),
]
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
run源碼:
def run(addr, port, wsgi_handler, ipv6=False, threading=False):
server_address = (addr, port)
if threading:
httpd_cls = type(str('WSGIServer'), (socketserver.ThreadingMixIn, WSGIServer), {})
else:
httpd_cls = WSGIServer
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
httpd.set_app(wsgi_handler)
httpd.serve_forever()
到這里,項目的初始化完成。通過WSGIServer來監聽請求,通過WSGIHandler來處理請求。
二、項目運行時處理request和response的核心過程分析:
2、WSGIServer接受到response后,把status、headers、response以及其他相關的信息組合在一起構造成一個響應報文,然后返回給客戶端。
三、從請求到響應過程中與中間件的交互:
1.請求到達Request Middlewares, 2.URLConf通過urls.py文件和請求的URL找到相應的View 3.View Middlewares被訪問,它同樣可以對request做一些處理或者直接返回response 4.調用View中的函數 5.View中的方法可以選擇性的通過Models訪問底層的數據 6.所有的Model-to-DB的交互都是通過manager完成的 7.如果需要,Views可以使用一個特殊的Context 8.Context被傳給Template用來生成頁面 a.Template使用Filters和Tags去渲染輸出 b.輸出被返回到View c.HTTPResponse被發送到Response Middlewares d.任何Response Middlewares都可以豐富response或者返回一個完全不同的response e.Response返回到瀏覽器,呈現給用戶
中間件顧名思義,是介於request與response處理之間的一道處理過程,相對比較輕量級,並且在全局上改變django的輸入與輸出。因為改變的是全局,所以需要謹慎實用,用不好會影響到性能。
如果你想修改請求,例如被傳送到view中的HttpRequest對象。 或者你想修改view返回的HttpResponse對象,這些都可以通過中間件來實現。
可能你還想在view執行之前做一些操作,這種情況就可以用 middleware來實現。
Django默認的Middleware:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
每一個中間件都有具體的功能。
自定義中間件
中間件中一共有四個方法:
process_request process_view process_exception process_response
process_request,process_response
當用戶發起請求的時候會依次經過所有的的中間件,這個時候的請求時process_request,最后到達views的函數中,views函數處理后,在依次穿過中間件,這個時候是process_response,最后返回給請求者。

上述截圖中的中間件都是django中的,我們也可以自己定義一個中間件,我們可以自己寫一個類,但是必須繼承MiddlewareMixin
導入語法:
from django.utils.deprecation import MiddlewareMixin
in views:
def index(request):
print("view函數...")
return HttpResponse("OK")
in Mymiddlewares.py:
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class Md1(MiddlewareMixin):
def process_request(self,request):
print("Md1請求")
def process_response(self,request,response):
print("Md1返回")
return response
class Md2(MiddlewareMixin):
def process_request(self,request):
print("Md2請求")
#return HttpResponse("Md2中斷")
def process_response(self,request,response):
print("Md2返回")
return response
結果:
Md1請求 Md2請求 view函數... Md2返回 Md1返回
注意:如果當請求到達請求2的時候直接不符合條件返回,即return HttpResponse("Md2中斷"),程序將把請求直接發給中間件2返回,然后依次返回到請求者,結果如下:
返回Md2中斷的頁面,后台打印如下:
Md1請求 Md2請求 Md2返回 Md1返回
流程圖如下:

process_view
process_view(self, request, callback, callback_args, callback_kwargs)
Mymiddlewares.py修改如下
from django.utils.deprecation import MiddlewareMixin
from django.shortcuts import HttpResponse
class Md1(MiddlewareMixin):
def process_request(self,request):
print("Md1請求")
#return HttpResponse("Md1中斷")
def process_response(self,request,response):
print("Md1返回")
return response
def process_view(self, request, callback, callback_args, callback_kwargs):
print("Md1view")
class Md2(MiddlewareMixin):
def process_request(self,request):
print("Md2請求")
return HttpResponse("Md2中斷")
def process_response(self,request,response):
print("Md2返回")
return response
def process_view(self, request, callback, callback_args, callback_kwargs):
print("Md2view")
結果如下:
Md1請求
Md2請求
Md1view
Md2view
view函數...
Md2返回
Md1返回

