django處理一個Request的過程是首先經過django 中間件,而後再經過默認的URL方式進行的。因此說咱們要作的就是在django 中間件這個地方把全部Request攔截住,用咱們本身的方式完成處理之後直接返回Response,那麼咱們能夠簡化原來的設計思路,把中間件不能處理的 Request通通無論,丟給Django去處理。python
若是你要在用戶登陸或者其它的處理過程當中完成本身的一些處理,好比進行權限控制,對返回結果做一些處理,可使用python的修飾器,但有個缺點就是要在每一個視圖前面都添加修飾器,當初我就是這麼作的,太累了。後來發現 django 中間件很是棒,能夠進行全局控制,並且能夠提升性能。提倡這種dry的哲學風格設計很是的有意思,django
先說下django 中間件的安裝方法:瀏覽器
爲了激活中間件組件,把它添加到你的settings模塊的MIDDLEWARE_CLASSES列表中,在MIDDLEWARE_CLASSES裏,每一箇中間件組件經過一個字符串來表示:完整的到中間件的類名的Python路徑,例如,這裏是經過django-admin.py startproject建立的 session
默認的MIDDLEWARE_CLASSES:app
MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', #'decorators.middleware.DecoratorsMiddleware', # Uncomment the next line for simple clickjacking protection: # 'django.middleware.clickjacking.XFrameOptionsMiddleware', )
Django安裝部須要任何中間件--例如MIDDLEWARE_CLASSES能夠爲空,若是你想這樣的話--可是強烈建議你使用CommonMiddleware 順序是有意義的,在請求和視圖階段,Django使用MIDDLEWARE_CLASSES給定的順序申請中間件,而在應答和異常階段,Django使用相反的順序申請中間件,即DjangoMIDDLEWARE_CLASSES看成一種視圖方法的"包裝器",在請求時,它自頂向下申請這個列表的中間件到視圖,而在應答時它反序進行.函數
再說下django 中間件的定義方法:性能
* 請求預處理:process_request(self, request) :url
該方法在請求被接收和URL被解析來決定運行哪一個視圖以前當即調用,它傳遞你可能想修改的HttpRequest對象 process_request()應該返回None或者HttpResponse對象,若是它返回None,Django將繼續處理該請求,執行任何其它的中間件而後是合適的視圖。若是請求中間件返回HttpResponse對象,Django將不會再調用其它任何中間件(任何類型)或者合適的視圖,它將返回該應答。 spa
* 視圖預處理:process_view(self, request, view, args, kwargs) :設計
該方法在請求中間件運行後和URL被解析到一個視圖後和視圖實際上被調用以前被調用,
參數說明:
* request HttpRequest對象
* view, Django將調用來執行該請求的視圖函數,它是實際上的方法對象自己,而不是方法名字符串
* args 將被傳遞給視圖的位置參數列表,不包括request參數(它一直是視圖的第一個參數)
* kwargs 將被傳遞給視圖的關鍵字參數字典
像process_request()同樣,process_view()應該返回None或者HttpResponse對象,若是它返回None,Django將繼續處理請求執行任何其它的視圖中間件而後是合適的視圖,若是視圖中間件返回HttpResponse對象,Django將不會再調用其它任何中間件或者合適的視圖,它將返回該應答
* 應答後處理:process_response(self, request, response)
該方法在視圖方法已經調用和應答生成後調用,這是中間件修改應答輸出的地方,輸出壓縮(見下)是應答中間件的一個顯然的應用參數應該很是自明瞭--request是請求對象,response是從視圖返回的應答對象不像請求和視圖中間件,它們能夠返回None,process_response()必須返回一個HttpResponse對象,該應答能夠是傳遞給該
方法的原始應答(可能被修改了)或者新的應答
* 異常後處理:process_exception(self, request, exception)
該方法只在出錯而且視圖觸發不可捕獲的異常時調用,不包括Http404異常,你可使用這個鉤子來發送錯誤通知,在一個日誌文件記錄信息,或者甚至嘗試自動恢復該錯誤。該方法的參數是咱們一直處理的一樣的request對象和視圖方法觸發的真正的Exception對象exception。process_exception()可能返回一個做爲應答顯示給瀏覽器的HttpResponse或者返回None來繼續Django內建的異常處理。
好比咱們寫了個例子
MIDDLEWARE_CLASSES = (
'apps.auth.middleware.DecoratorsMiddleware',
)
而後DecoratorsMiddleware定義的方法是:
#coding=utf-8 import urllib from django.template import RequestContext from django.shortcuts import render_to_response class DecoratorsMiddleware(object): """ 若是返回的對象是字典,就對它進行處理 """ def process_response(self, request, response): if type(response) == dict: param_dict = {} for k,v in request.GET.items(): if k == 'last_id': param_dict['last_id'] = response['ret'].get('last_id','') else: param_dict[k] = v.encode('utf-8') if not param_dict.get('last_id'): param_dict['last_id'] = response['ret'].get('last_id','') response['ret']['params'] = urllib.urlencode(param_dict) response['ret'] = dict(response['ret'], **param_dict) return render_to_response( response['template'], response['ret'], RequestContext(request, {}), ) return response
最後總結一下django 中間件不是很難,用一下就應該比較清楚了。