search

Home  >  Q&A  >  body text

flask user permission decorator - Stack Overflow

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中文网2752 days ago674

reply all(2)I'll reply

  • 迷茫

    迷茫2017-05-18 10:52:23

    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

    reply
    0
  • 给我你的怀抱

    给我你的怀抱2017-05-18 10:52:23

    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

    reply
    0
  • Cancelreply