flask user permission decorator - Stack Overflow
PHP中文网
PHP中文网 2017-05-18 10:50:23
0
2
683

After reading the book, I found that this code is a bit confusing, and the decorator is a bit unclear. I hope you can help me analyze this code! !

from functools import wraps
from flask import abort
from flask_login import current_user
from .models import Permission


def 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 decorator


def admin_required(f):
    return permission_required(Permission.ADMINISTER)(f)
PHP中文网
PHP中文网

认证高级PHP讲师

reply all(2)
迷茫

First you need to understand the principle of decorators:

@abcd
def f():
    pass

is actually equivalent to the following statement:

def f():
    pass
f=abcd(f)

We now have a function abcd. The essence of this function is: it accepts another function as a parameter and returns a function. (As for what the returned function is used for, that's up to you). At this time, abcd is just a function, not a modifier.
And because the following requirement is very common: there is an old function, and we want to define a new function. This new function is generally similar in function to the old function, but has a little more new functions, such as printing a date and judging an individual. Permissions or something. Then the old function will definitely be called during the process of defining a new function. However, the new function actually does not change much, and the old function is often useless (because we usually use new functions later), so in order to prevent the namespace from changing To avoid confusion and facilitate development, we can simply use the name of the old function to represent the new function. That is, after defining a new function, we change its name back to the previous f, and the previous f is No more. So we can do this: Define a function abcd, which accepts a function f and returns a new function, and then assigns its return value (new function) to f (the function name in python can also be assigned a value, becoming another function). This is actually what my second piece of code above does. Because this requirement is so common, Python defines a syntax specifically for it. Don’t you want f=abcd(f) every time? Then just add @abcd in front of the def statement of f. Don’t write the following sentence every time. It is not only troublesome, but also easy to misunderstand sometimes. At this time, abcd becomes the decorator. Understanding this equivalence relationship, your function will be easier to understand: when you use it somewhere, it will look like this

@permission_required(permission)
def old():
    pass

is equivalent to
def old():
    pass
old = permission_required(permission)(old)

The priorities are the same, operations are from left to right, and the function defined here is calculated first.

The process is:

old = permission_required(permission)(old)
-> old = decorator(old)
-> old = decorated_function
给我你的怀抱

Hope the following code will be helpful to you

from functools import wraps

def 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 decorator


def admin_required_true(f):
    """装饰器函数,返回装饰器
    """
    return permission_required(True)(f)

def admin_required_false(f):
    """装饰器函数,返回装饰器
    """
    return permission_required(False)(f)

@admin_required_true
def foo():
    """使用装饰器
    """
    print 'foo'
    
@admin_required_false
def bar():
    """使用装饰器
    """
    print 'bar'

foo()
bar()

Run result:

foo
403
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template