python - flask 用戶權限修飾器
問題描述
看書發現這段代碼有點云里霧里,裝飾器有點昏,希望幫我解析下這段代碼!!
from functools import wrapsfrom flask import abortfrom flask_login import current_userfrom .models import Permissiondef permission_required(permission): def decorator(f):@wraps(f)def decorated_function(*args, **kwargs): if not current_user.can(permission):abort(403) return f(*args, **kwargs)return decorated_function return decoratordef admin_required(f): return permission_required(Permission.ADMINISTER)(f)
問題解答
回答1:首先你要理解裝飾器的原理:
@abcddef f(): pass
實際上與下面的語句等價:
def f(): passf=abcd(f)
我們現在有一個函數abcd,這個函數的本質是:接受另一個函數當做參數,且返回一個函數。(至于返回的函數用來干嘛那就是你的事了)。這時候,abcd僅僅就是個函數而已,還不是修飾器。而由于以下這個需求十分的常見:有一個舊函數,我們又想定義一個新函數,這個新函數大體上功能與舊函數接近,只是多了一點點的新功能,比如打印個日期,判斷個權限什么的。那么定義新函數的過程中肯定會調用這個舊函數,然而新函數其實改變不大,舊函數往往也沒用了(因為一般我們后面都是用的新函數了),那么為了不讓命名空間變得混亂和方便開發,我們可以簡單的就用舊函數的名字來表示新函數,也就是在定義完了一個新函數之后,我們把它的名字又變回以前的f,而以前的f就不要了。所以我們可以這樣做:定義一個函數abcd,它接受一個函數f,且返回一個新的函數,再把它的返回值(新函數),再賦值給f(python里函數名也可以賦值,成為另一個函數)。這實際上就是我上面的第二段代碼做的事情。由于這個需求太過常見,所以python專門為它定義了語法。你不是每次都要f=abcd(f)嗎,那你就直接在f的def語句前面加個@abcd得了,也別每次再寫后面那句了,不僅麻煩,有時還容易誤解。這時候,abcd就成為了裝飾器。了解了這個等價關系,你的函數就好理解了:當你在某處使用的時候,是這樣的
@permission_required(permission)def old(): pass
等價于
def old(): passold = permission_required(permission)(old)
優先級相同,運算從左到右,首先計算permission_required(permission),它返回decorator是一個函數,這時候變成old = decorator(old)為了滿足成為修飾器的要求,這個decorator應當返回一個新函數才行,在這里就是decorated_function,所以原賦值語句變成old = decorated_function。到這里比較清晰了,把一個函數的名字賦值給一個變量(old),所以old就變成了decorated_function這里所定義的函數。過程也就是:
old = permission_required(permission)(old)-> old = decorator(old)-> old = decorated_function回答2:
希望下面代碼對你有幫助
from functools import wrapsdef permission_required(permission): '''返回裝飾器,裝飾器中使用入參 permission ''' def decorator(f):@wraps(f)def decorated_function(*args, **kwargs): if not permission:print ’403’return return f(*args, **kwargs)return decorated_function return decoratordef admin_required_true(f): '''裝飾器函數,返回裝飾器 ''' return permission_required(True)(f)def admin_required_false(f): '''裝飾器函數,返回裝飾器 ''' return permission_required(False)(f)@admin_required_truedef foo(): '''使用裝飾器 ''' print ’foo’ @admin_required_falsedef bar(): '''使用裝飾器 ''' print ’bar’foo()bar()
運行結果:
foo403
相關文章:
1. mysql日期類型默認值’0000-00-00’ 報錯2. 求救一下,用新版的phpstudy,數據庫過段時間會消失是什么情況?3. mysql replace 死鎖4. mysql - C#連接數據庫時一直這一句出問題int i = cmd.ExecuteNonQuery();5. MYSQL 根據兩個字段值查詢 但兩個值的位置可能是互換的,這個怎么查?6. extra沒有加載出來7. android - 安卓做前端,PHP做后臺服務器 有什么需要注意的?8. javascript - 微信網頁開發從菜單進入頁面后,按返回鍵沒有關閉瀏覽器而是刷新當前頁面,求解決?9. php傳對應的id值為什么傳不了啊有木有大神會的看我下方截圖10. mysql - ubuntu開啟3306端口失敗,有什么辦法可以解決?
