Django教程筆記之中間件middleware詳解
中間件介紹
中間件顧名思義,是介于request與response處理之間的一道處理過(guò)程,相對(duì)比較輕量級(jí),并且在全局上改變django的輸入與輸出。因?yàn)楦淖兊氖侨?,所以需要?jǐn)慎實(shí)用,用不好會(huì)影響到性能。
每個(gè)中間件都會(huì)負(fù)責(zé)一個(gè)功能,例如,AuthenticationMiddleware,與sessions處理相關(guān)。
激活中間件
需要在settings.py配置文件中,配置MIDDLEWARE_CLASSES:
MIDDLEWARE_CLASSES = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
當(dāng)然你也可以不試用任何的中間件,這個(gè)可以設(shè)置為空。
中間件順序
一般我們我們從瀏覽器發(fā)出一個(gè)請(qǐng)求 Request,得到一個(gè)響應(yīng)后的內(nèi)容 HttpResponse ,這個(gè)請(qǐng)求傳遞到 Django的過(guò)程如下,process request 和 process response的執(zhí)行順序正好相反,如下圖所示:

也就是說(shuō),每一個(gè)請(qǐng)求都是先通過(guò)中間件中的 process_request 函數(shù),這個(gè)函數(shù)返回 None 或者 HttpResponse 對(duì)象,如果返回前者,繼續(xù)處理其它中間件,如果返回一個(gè) HttpResponse,就處理中止,返回到網(wǎng)頁(yè)上。
中間件不用繼承自任何類(lèi)(可以繼承 object ),下面一個(gè)中間件大概的樣子:
class CommonMiddleware(object): def process_request(self, request): return None def process_response(self, request, response): return response
需要用到的幾個(gè)hook:
- process_request()
- process_exception() (only if the view raised an exception)
- process_template_response()
- process_response()
常用的中間件組件:
1. Sessions
2. Authentication
3. CSRF Protection
4. GZipping Content
例如,比如我們要做一個(gè) 流量統(tǒng)計(jì)
class BlockedIpMiddleware(object): def process_request(self, request): ...數(shù)據(jù)庫(kù)拿access值 access = access+1 ...存起來(lái),類(lèi)似這個(gè)原理
這里的代碼的功能就是 簡(jiǎn)單的訪問(wèn)一次加一次,把這個(gè)中間件的 Python 路徑寫(xiě)到settings.py中
MIDDLEWARE_CLASSES = ( 'zjj.middleware.BlockedIpMiddleware', ...其它的中間件 )
Django 會(huì)從 MIDDLEWARE_CLASSES 中按照從上到下的順序一個(gè)個(gè)執(zhí)行中間件中的 process_request 函數(shù),而其中 process_response 函數(shù)則是最前面的最后執(zhí)行。
二,再比如,我們?cè)诰W(wǎng)站放到服務(wù)器上正式運(yùn)行后,DEBUG改為了 False,這樣更安全,但是有時(shí)候發(fā)生錯(cuò)誤不能顯示錯(cuò)誤詳情頁(yè)面,有沒(méi)有辦法處理好這兩個(gè)事情呢?
普通訪問(wèn)者看到的是友好的報(bào)錯(cuò)信息
管理員看到的是錯(cuò)誤詳情,以便于修復(fù) BUG
當(dāng)然可以有,利用中間件就可以做到!代碼如下:
import sys
from django.views.debug import technical_500_response
from django.conf import settings
class UserBasedExceptionMiddleware(object):
def process_exception(self, request, exception):
if request.user.is_superuser or request.META.get('REMOTE_ADDR') in settings.INTERNAL_IPS:
return technical_500_response(request, *sys.exc_info())
把這個(gè)中間件像上面一樣,加到你的 settings.py 中的 MIDDLEWARE_CLASSES 中,可以放到最后,這樣可以看到其它中間件的 process_request的錯(cuò)誤。
當(dāng)訪問(wèn)者為管理員時(shí),就給出錯(cuò)誤詳情,比如訪問(wèn)本站的不存在的頁(yè)面。
普通人看到的是普通的 404(自己點(diǎn)開(kāi)看看),而我們卻可以看到。
三,分享一個(gè)簡(jiǎn)單的識(shí)別手機(jī)的中間件,更詳細(xì)的可以參考這個(gè):django-mobi
MOBILE_USERAGENTS = ("2.0 MMP","240x320","400X240","AvantGo","BlackBerry",
"Blazer","Cellphone","Danger","DoCoMo","Elaine/3.0","EudoraWeb",
"Googlebot-Mobile","hiptop","IEMobile","KYOCERA/WX310K","LG/U990",
"MIDP-2.","MMEF20","MOT-V","NetFront","Newt","Nintendo Wii","Nitro",
"Nokia","Opera Mini","Palm","PlayStation Portable","portalmmm","Proxinet",
"ProxiNet","SHARP-TQ-GX10","SHG-i900","Small","SonyEricsson","Symbian OS",
"SymbianOS","TS21i-10","UP.Browser","UP.Link","webOS","Windows CE",
"WinWAP","YahooSeeker/M1A1-R2D2","iPhone","iPod","Android",
"BlackBerry9530","LG-TU915 Obigo","LGE VX","webOS","Nokia5800")
class MobileTemplate(object):
"""
If a mobile user agent is detected, inspect the default args for the view
func, and if a template name is found assume it is the template arg and
attempt to load a mobile template based on the original template name.
"""
def process_view(self, request, view_func, view_args, view_kwargs):
if any(ua for ua in MOBILE_USERAGENTS if ua in
request.META["HTTP_USER_AGENT"]):
template = view_kwargs.get("template")
if template is None:
for default in view_func.func_defaults:
if str(default).endswith(".html"):
template = default
if template is not None:
template = template.rsplit(".html", 1)[0] + ".mobile.html"
try:
get_template(template)
except TemplateDoesNotExist:
pass
else:
view_kwargs["template"] = template
return view_func(request, *view_args, **view_kwargs)
return None
再舉一個(gè)本地化的中間件的例子:
class LocaleMiddleware(object): def process_request(self, request): if 'locale' in request.cookies: request.locale = request.cookies.locale else: request.locale = None def process_response(self, request, response): if getattr(request, 'locale', False): response.cookies['locale'] = request.locale
就是將cookies中的locale設(shè)置給request中的locale,供給后面使用。
這部分參考了django官方文檔以及網(wǎng)絡(luò)上的一些教程,這里也非常感謝這些前輩的分享。
總結(jié)
以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
使用darknet框架的imagenet數(shù)據(jù)分類(lèi)預(yù)訓(xùn)練操作
這篇文章主要介紹了使用darknet框架的imagenet數(shù)據(jù)分類(lèi)預(yù)訓(xùn)練操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2020-07-07
?python中pandas讀取csv文件?時(shí)如何省去csv.reader()操作指定列步驟
這篇文章主要介紹了?python中pandas讀取csv文件?時(shí)如何省去csv.reader()操作指定列步驟,對(duì)正在工作的你可能有一定的幫助,需要的朋友可以參考一下2022-01-01
transforms.Compose()函數(shù)的使用及說(shuō)明
這篇文章主要介紹了transforms.Compose()函數(shù)的使用及說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08
python3.8.1+selenium實(shí)現(xiàn)登錄滑塊驗(yàn)證功能
這篇文章主要介紹了python3.8.1+selenium解決登錄滑塊驗(yàn)證的問(wèn)題,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-05-05
如何利用python多線程爬取天氣網(wǎng)站圖片并保存
最近做個(gè)天 氣方面的APP需要用到一些天氣數(shù)據(jù),所以下面這篇文章主要給大家介紹了關(guān)于如何利用python多線程爬取天氣網(wǎng)站圖片并保存的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下2021-11-11

