|
裝飾器(decorator)可以說是Python的一個神器,它可以在不改變一個函數(shù)代碼和調(diào)用方式的情況下給函數(shù)添加新的功能(見一文看懂Python系列之裝飾器)。裝飾器廣泛用于權限校驗和緩存等場景,是學習Python Web開發(fā)的必備知識。Django項目中使用裝飾器可以讓代碼將變得更干凈、更可讀、更可維護。今天我就帶你看下Django自帶的常用裝飾器的應用場景及正確使用方法。 權限驗證 @login_required @login_required是Django最常用的一個裝飾器。其作用是在執(zhí)行視圖函數(shù)前先檢查用戶是否通過登錄身份驗證,并將未登錄的用戶重定向到指定的登錄url。其中l(wèi)ogin_url是可選參數(shù)。如果不設置,默認login_url是settings.py里設置的LOGIN_URL。 from django.contrib.auth.decorators import login_required @login_required(login_url='/accounts/login/') def my_view(request): ... @login_required還可以一個可選參數(shù)是redirect_field_name, 默認值是'next'。 from django.contrib.auth.decorators import login_required @login_required(redirect_field_name='my_redirect_field') def my_view(request): 注意: login_required裝飾器不會檢查用戶是否是is_active狀態(tài)。如果你想進一步限制登錄驗證成功的用戶對某些視圖函數(shù)的訪問,你需要使用更強大的@user_passes_test裝飾器。 @user_passes_test @user_passes_test裝飾器的作用是對登錄用戶對象的信息進行判斷,只有通過測試(返回值為True)的用戶才能訪問視圖函數(shù)。不符合條件的用戶會被跳轉(zhuǎn)到指定的登錄url。 @user_passes_test裝飾器有一個必選參數(shù),即對用戶對象信息進行判斷的函數(shù)。該函數(shù)必需接收user對象為參數(shù)。與@login_required類似,@user_passes_test還有兩個可選參數(shù)(login_url和redirect_field_name),這里就不多講了。 user_passes_test(func[,login_url=None, redirect_field_name=REDIRECT_FIELD_NAME]) 下例中@user_passes_test裝飾器對用戶的email地址結尾進行判斷,會把未通過測試的用戶會定向到登錄url。試想一個匿名用戶來訪問,她沒有email地址,顯然不能通過測試,登錄后再來吧。 注意: @user_passes_test不會自動的檢查用戶是否是匿名用戶, 但是@user_passes_test裝飾器還是可以起到兩層校驗的作用。一來檢查用戶是否登錄,二來檢查用戶是否符合某些條件,無需重復使用@login_required裝飾器。 我們?nèi)绻辉试Sis_active的登錄用戶訪問某些視圖,我們現(xiàn)在可以使用@user_passes_test裝飾器輕松地解決這個問題,如下所示: @permission_required @permission_required裝飾器的作用是檢查用戶用戶是否有特定權限,第一個參數(shù)perm是權限名,為必選, 第二個參數(shù)login_url為可選。 permission_required(perm[, login_url=None, raise_exception=False]) 下例檢查用戶是否有polls.can_vote的權限,沒有的話定向至login_url。如果你設置了raise_exception=True, 會直接返回403無權限的錯誤,而不會跳轉(zhuǎn)到登錄頁面。那么問題來了,我們需要先使用@login_required來驗證用戶是否登錄,再使用@permission_required裝飾器來查看登錄用戶是否具有相關權限嗎? 答案是不需要。如果一個匿名用戶來訪問這個視圖,顯然該用戶沒有相關權限,會自動定向至登錄頁面。 緩存 緩存是Django裝飾器很重要的一個應用場景。下面我們來看幾個主要的緩存裝飾器。注意: 使用以下裝飾器的前提是你已經(jīng)對緩存進行了相關設置(見Django基礎(8): 緩存Cache應用場景及工作原理,Cache設置及如何使用)。 @cache_page 該裝飾器可以接收緩存的時間作為參數(shù),比如下例緩存頁面15分鐘。 @cache_control 通常用戶將會面對兩種緩存: 他或她自己的瀏覽器緩存(私有緩存)以及他或她的提供者緩存(公共緩存)。 公共緩存由多個用戶使用,而受其它人的控制。 這就產(chǎn)生了你不想遇到的敏感數(shù)據(jù)的問題,比如說你的銀行賬號被存儲在公眾緩存中。 因此,Web 應用程序需要以某種方式告訴緩存那些數(shù)據(jù)是私有的,哪些是公共的。cache_control 裝飾器可以解決這個問題。 該修飾器負責在后臺發(fā)送相應的 HTTP 頭部。還有一些其他方法可以控制緩存參數(shù)。 例如, HTTP 允許應用程序執(zhí)行如下操作:
在 Django 中,可使用 cache_control 視圖修飾器指定這些緩存參數(shù)。 在下例中, cache_control 告訴緩存對每次訪問都重新驗證緩存并在最長 3600 秒內(nèi)保存所緩存版本。 在 cache_control() 中,任何合法的Cache-Control HTTP 指令都是有效的。下面是完整列表:
@vary_on_headers 缺省情況下,Django 的緩存系統(tǒng)使用所請求的路徑(如blog/article/1)來創(chuàng)建其緩存鍵。這意味著不同用戶請求同樣路徑都會得到同樣的緩存版本,不考慮客戶端user-agent, cookie和語言配置的不同, 除非你使用Vary頭部通知緩存機制需要考慮請求頭里的cookie和語言的不同。 要在 Django 完成這項工作,可使用便利的 vary_on_headers 視圖裝飾器。例如下面代碼告訴Django讀取緩存數(shù)據(jù)時需要同時考慮User-Agent和Cookie的不同。與此類似的裝飾器還有@vary_on_cookie。 @never_cache 如果你想用頭部完全禁掉緩存, 你可以使用@never_cache裝飾器。如果你不在視圖中使用緩存,服務器端是肯定不會緩存的,然而用戶的客戶端如瀏覽器還是會緩存一些數(shù)據(jù),這時你可以使用never_cache禁用掉客戶端的緩存。 其它常用裝飾器 @method_decorator 前面的案例中,我們的裝飾器都是直接使用在函數(shù)視圖上的。如果需要在基于類的視圖上使用裝飾器,我們需要使用到@method_decorator這個裝飾器, 它的作用是將類偽裝成函數(shù)方法。@method_decorator第一個參數(shù)一般是需要使用的裝飾器名。 @require_http_methods 該裝飾器的作用是限制用戶的請求方法。如下例中僅接收GET和POST方法。與此類似的裝飾器還有@require_POST, @require_GET和@require_safe。 @gzip_page 該裝飾器可以壓縮內(nèi)容,前提是用戶客戶端允許內(nèi)容壓縮的話。使用方法如下: 使用多重裝飾器 你可以在一個函數(shù)或基于類的視圖上使用多重裝飾器,但一定要考慮裝飾器執(zhí)行的先后順序。比如下例中會先執(zhí)行@never_cache, 再執(zhí)行@login_required。 小結 本文總結了Django自帶的常用裝飾器的應用場景及如何正確使用它們。下文我們將介紹如何自定義Django裝飾器并分享幾個常用的自定義裝飾器,歡迎關注。 大江狗 2019.3 Django Web開發(fā)核心基礎知識 Django網(wǎng)站開發(fā)四件套是如何遵循MVC軟件設計模式的? Django基礎核心技術介紹(1): Model模型的介紹與設計 Django基礎核心技術介紹(3): View視圖詳解與通用視圖 Django基礎核心技術介紹(4): Template模板的編寫及過濾器 Django基礎核心結束介紹(5): Forms表單的使用與設計 Django基礎(7): cookie和session應用場景及如何使用 Django基礎(8): 緩存Cache應用場景及工作原理,Cache設置及如何使用 Django基礎(10): URL重定向的HttpResponseDirect, redirect和reverse的用法 Django基礎(11): 表單集合Formset的高級用法 Django基礎(12): Request對象詳解及開發(fā)顯示用戶IP地址和瀏覽器APP Django基礎(13): 深夜放干貨。QuerySet特性及高級使用技巧,如何減少數(shù)據(jù)庫的訪問,節(jié)省內(nèi)存,提升網(wǎng)站性能。 Django基礎(14): 通過next參數(shù)實現(xiàn)登錄后跳轉(zhuǎn)回到前一頁的3種方法 Django基礎(15): 模板過濾器(filter)的工作原理及如何自定義模板過濾器 Django基礎(16): 模板標簽(tags)的分類及如何自定義模板標簽 Django基礎(17): 如何上傳處理文件及Ajax文件上傳示范(附GitHub源碼) Django基礎(18): 實現(xiàn)文件下載的3種方法及文件私有化 Django基礎(19): Django Admin管理后臺詳解(上) Django基礎(20): Django admin管理后臺詳解(中)如何自定義list_display和list_filter Django基礎(21): Django admin管理后臺詳解(下)如何自定義actions, 表單和美化admin Django基礎(22): 數(shù)據(jù)庫的設計之自定義表名,建立索引和使用多數(shù)據(jù)庫主從配置 Django基礎(23): 權限管理(permissions)與用戶組(group)詳解 Django基礎(24): aggregate和annotate方法使用詳解與示例 Django基礎(25):settings.py設置選項深入解讀。大江狗精品原創(chuàng)。 Django基礎(26): 常用裝飾器應用場景及正確使用方法 Django基礎(27): 快捷函數(shù)(shortcut function)模塊詳解Django基礎(28): 如何設計充滿陷阱的優(yōu)美URL Django基礎(28): 如何設計充滿陷阱的優(yōu)美URL Django Web開發(fā)實戰(zhàn)案例 Django 2.0 項目實戰(zhàn)(1): 擴展Django自帶User模型,實現(xiàn)用戶注冊與登錄 Django 2.0 項目實戰(zhàn)(2): 編輯用戶個人資料,擴展Django后臺UserAdmin Django 2.0項目實戰(zhàn)(3): 密碼重置與退出登錄 Django 2.0 項目實戰(zhàn): 圖片上傳與顯示 Django 2.0 項目實戰(zhàn): PDF文件頁面提取 Django 2.0 項目實戰(zhàn): PDF文件合并 Django 2.0 項目實戰(zhàn):輸出樹形分類目錄 Django 2.0 項目實戰(zhàn): 網(wǎng)頁計數(shù)器統(tǒng)計瀏覽次數(shù) Django 2.0 項目實戰(zhàn): 利用AJAX實現(xiàn)博文實時搜索 Django 1.X和2.0下利用自帶分頁Paginator類實現(xiàn)分頁功能 Django實戰(zhàn): 利用Ajax生成聯(lián)動下拉菜單 世界那么大,我想去看看。Django仿制微信朋友圈九宮格相冊(1) 世界那么大,我想去看看。Django仿制微信朋友圈九宮格相冊(2) django-allauth教程(1): 安裝,用戶注冊,登錄,郵箱驗證和密碼重置(更新) django-allauth教程(2): 用戶個人資料UserProfile擴展與編輯 django-allauth教程(3): 第三方賬戶授權登錄(以百度賬號為例) django-allauth教程(4): 美化模板,自定義郵件和消息內(nèi)容 Django+jQuery cropper實現(xiàn)用戶頭像裁剪, 預覽和上傳[原創(chuàng)] Django實戰(zhàn)教程: 開發(fā)餐廳在線點評網(wǎng)站(1) Django實戰(zhàn)教程: 開發(fā)餐廳在線點評網(wǎng)站(2) Django實戰(zhàn)教程: 開發(fā)企業(yè)級應用智能文檔管理系統(tǒng)smartdoc(1) Django實戰(zhàn)教程: 開發(fā)企業(yè)級應用智能文檔管理系統(tǒng)smartdoc(2)之權限管理 Django實戰(zhàn)教程: 開發(fā)企業(yè)級應用智能文檔管理系統(tǒng)smartdoc(3)附GitHub代碼地址 Django實戰(zhàn)專題: 開發(fā)專業(yè)博客(1)之內(nèi)容管理后臺開發(fā) Django實戰(zhàn)專題: 開發(fā)專業(yè)博客(2)之母子類別導航和添加富文本編輯器CKEditor Django實戰(zhàn)專題: 開發(fā)專業(yè)博客(3)之仿微信評論點贊功能 Django實戰(zhàn): Python爬取鏈家上海二手房信息,存入數(shù)據(jù)庫并在前端顯示 Django應用實戰(zhàn): 編寫你自己的PDF編輯器, 實現(xiàn)PDF頁面提取, 頁面合并與替換。 如何在阿里云Ubuntu服務器通過uWSGI和Nginx部署Django項目教程-大江狗原創(chuàng)出品 Django Web開發(fā)學習筆記 淺談Django Model創(chuàng)建對象的save與create方法 Django常用命令django-admin.py和manage.py用法詳解 Django自定義圖片和文件上傳路徑(upload_to)的2種方式 Django ContentTypes框架詳解及使用場景介紹 Django更改模型過程中易出現(xiàn)的問題及解決方案 2019新年第一篇: SQLite的優(yōu)缺點及Django配置MySQL數(shù)據(jù)庫 裝飾器(decorator)可以說是Python的一個神器,它可以在不改變一個函數(shù)代碼和調(diào)用方式的情況下給函數(shù)添加新的功能(見一文看懂Python系列之裝飾器)。裝飾器廣泛用于權限校驗和緩存等場景,是學習Python Web開發(fā)的必備知識。Django項目中使用裝飾器可以讓代碼將變得更干凈、更可讀、更可維護。今天小編我就帶你看下Django自帶的常用裝飾器的應用場景及正確使用方法。 權限驗證 @login_required @login_required是Django最常用的一個裝飾器。其作用是在執(zhí)行視圖函數(shù)前先檢查用戶是否通過登錄身份驗證,并將未登錄的用戶重定向到指定的登錄url。其中l(wèi)ogin_url是可選參數(shù)。如果不設置,默認login_url是settings.py里設置的LOGIN_URL。 from django.contrib.auth.decorators import login_required @login_required(login_url='/accounts/login/') def my_view(request): ... @login_required還可以一個可選參數(shù)是redirect_field_name, 默認值是'next'。 from django.contrib.auth.decorators import login_required @login_required(redirect_field_name='my_redirect_field') def my_view(request): 注意: login_required裝飾器不會檢查用戶是否是is_active狀態(tài)。如果你想進一步限制登錄驗證成功的用戶對某些視圖函數(shù)的訪問,你需要使用更強大的@user_passes_test裝飾器。 @user_passes_test @user_passes_test裝飾器的作用是對登錄用戶對象的信息進行判斷,只有通過測試(返回值為True)的用戶才能訪問視圖函數(shù)。不符合條件的用戶會被跳轉(zhuǎn)到指定的登錄url。 @user_passes_test裝飾器有一個必選參數(shù),即對用戶對象信息進行判斷的函數(shù)。該函數(shù)必需接收user對象為參數(shù)。與@login_required類似,@user_passes_test還有兩個可選參數(shù)(login_url和redirect_field_name),這里就不多講了。 user_passes_test(func[,login_url=None, redirect_field_name=REDIRECT_FIELD_NAME]) 下例中@user_passes_test裝飾器對用戶的email地址結尾進行判斷,會把未通過測試的用戶會定向到登錄url。試想一個匿名用戶來訪問,她沒有email地址,顯然不能通過測試,登錄后再來吧。 注意: @user_passes_test不會自動的檢查用戶是否是匿名用戶, 但是@user_passes_test裝飾器還是可以起到兩層校驗的作用。一來檢查用戶是否登錄,二來檢查用戶是否符合某些條件,無需重復使用@login_required裝飾器。 我們?nèi)绻辉试Sis_active的登錄用戶訪問某些視圖,我們現(xiàn)在可以使用@user_passes_test裝飾器輕松地解決這個問題,如下所示: @permission_required @permission_required裝飾器的作用是檢查用戶用戶是否有特定權限,第一個參數(shù)perm是權限名,為必選, 第二個參數(shù)login_url為可選。 permission_required(perm[, login_url=None, raise_exception=False]) 下例檢查用戶是否有polls.can_vote的權限,沒有的話定向至login_url。如果你設置了raise_exception=True, 會直接返回403無權限的錯誤,而不會跳轉(zhuǎn)到登錄頁面。那么問題來了,我們需要先使用@login_required來驗證用戶是否登錄,再使用@permission_required裝飾器來查看登錄用戶是否具有相關權限嗎? 答案是不需要。如果一個匿名用戶來訪問這個視圖,顯然該用戶沒有相關權限,會自動定向至登錄頁面。 緩存 緩存是Django裝飾器很重要的一個應用場景。下面我們來看幾個主要的緩存裝飾器。注意: 使用以下裝飾器的前提是你已經(jīng)對緩存進行了相關設置(見Django基礎(8): 緩存Cache應用場景及工作原理,Cache設置及如何使用)。 @cache_page 該裝飾器可以接收緩存的時間作為參數(shù),比如下例緩存頁面15分鐘。 @cache_control 通常用戶將會面對兩種緩存: 他或她自己的瀏覽器緩存(私有緩存)以及他或她的提供者緩存(公共緩存)。 公共緩存由多個用戶使用,而受其它人的控制。 這就產(chǎn)生了你不想遇到的敏感數(shù)據(jù)的問題,比如說你的銀行賬號被存儲在公眾緩存中。 因此,Web 應用程序需要以某種方式告訴緩存那些數(shù)據(jù)是私有的,哪些是公共的。cache_control 裝飾器可以解決這個問題。 該修飾器負責在后臺發(fā)送相應的 HTTP 頭部。還有一些其他方法可以控制緩存參數(shù)。 例如, HTTP 允許應用程序執(zhí)行如下操作:
在 Django 中,可使用 cache_control 視圖修飾器指定這些緩存參數(shù)。 在下例中, cache_control 告訴緩存對每次訪問都重新驗證緩存并在最長 3600 秒內(nèi)保存所緩存版本。 在 cache_control() 中,任何合法的Cache-Control HTTP 指令都是有效的。下面是完整列表:
@vary_on_headers 缺省情況下,Django 的緩存系統(tǒng)使用所請求的路徑(如blog/article/1)來創(chuàng)建其緩存鍵。這意味著不同用戶請求同樣路徑都會得到同樣的緩存版本,不考慮客戶端user-agent, cookie和語言配置的不同, 除非你使用Vary頭部通知緩存機制需要考慮請求頭里的cookie和語言的不同。 要在 Django 完成這項工作,可使用便利的 vary_on_headers 視圖裝飾器。例如下面代碼告訴Django讀取緩存數(shù)據(jù)時需要同時考慮User-Agent和Cookie的不同。與此類似的裝飾器還有@vary_on_cookie。 @never_cache 如果你想用頭部完全禁掉緩存, 你可以使用@never_cache裝飾器。如果你不在視圖中使用緩存,服務器端是肯定不會緩存的,然而用戶的客戶端如瀏覽器還是會緩存一些數(shù)據(jù),這時你可以使用never_cache禁用掉客戶端的緩存。 其它常用裝飾器 @method_decorator 前面的案例中,我們的裝飾器都是直接使用在函數(shù)視圖上的。如果需要在基于類的視圖上使用裝飾器,我們需要使用到@method_decorator這個裝飾器, 它的作用是將類偽裝成函數(shù)方法。@method_decorator第一個參數(shù)一般是需要使用的裝飾器名。 @require_http_methods 該裝飾器的作用是限制用戶的請求方法。如下例中僅接收GET和POST方法。與此類似的裝飾器還有@require_POST, @require_GET和@require_safe。 @gzip_page 該裝飾器可以壓縮內(nèi)容,前提是用戶客戶端允許內(nèi)容壓縮的話。使用方法如下: 使用多重裝飾器 你可以在一個函數(shù)或基于類的視圖上使用多重裝飾器,但一定要考慮裝飾器執(zhí)行的先后順序。比如下例中會先執(zhí)行@never_cache, 再執(zhí)行@login_required。 小結 本文總結了Django自帶的常用裝飾器的應用場景及如何正確使用它們。下文我們將介紹如何自定義Django裝飾器并分享幾個常用的自定義裝飾器,歡迎關注。 大江狗 2019.3 |
|
|