Flask-Login中@login_manager.user_loader

之前一直知道装饰器可以增强一个已经存在的方法,Python也提供了annotation的方法,很好用. 但是再看flask login的扩展包的时候. 发现装饰器还可以实现回调函数的注册功能.

flask login就是通过下面的装饰器,来注册回调函数,当没有sessionID时,通过装饰器指定的函数来读取用户到session中.

@login_manager.user_loader

下面写了一个简单的测试例子来演示这个功能.

import time  
import functools  
class Test():  
     
    #/**feature将调用callback(), 但是在Test中并没有真正的定义callback**/  
    def feature(self):  
        self.callback()  
      
    def decorate(self, func):  
        self.callback=func  
        return func  
  
test =  Test()  
  
  
#/**将foo注册为回调函数*//  
@test.decorate  
def foo():  
    print 'in foo()'  
  
#/**调用feature将触发回调函数**/      
test.feature()  

输出结果如下:

in foo()

参考源码:
对于函数login_user(),当你调用他的时候会设置session[‘user_id’] = user_id;

对于装饰器@login_manager.user_loader,在user_loader(self, callback)中设置的是self.user_callback = callback,即注册了load_user()这个自定义的callback;

def user_loader(self, callback):
        '''
        This sets the callback for reloading a user from the session. The
        function you set should take a user ID (a ``unicode``) and return a
        user object, or ``None`` if the user does not exist.

        :param callback: The callback for retrieving a user object.
        :type callback: callable
        '''
        self.user_callback = callback
        return callback

对于这个load_user()的使用,即self.callback的使用,参见方法reload_user(self, user=None),
他的作用就是即使你的user参数无值,也可以通过调用self.callback来得到这个user,并把这个user赋值给ctx.user。

@login_manager.user_loader
def load_user(user_id):
        return User.query.get(int(user_id))

调用login_manager.reload_user将触发回调函数load_user

def reload_user(self, user=None):
        ctx = _request_ctx_stack.top

        if user is None:
            user_id = session.get('user_id')
            if user_id is None:
                ctx.user = self.anonymous_user()
            else:
                if self.user_callback is None:
                    raise Exception(
                        "No user_loader has been installed for this "
                        "LoginManager. Add one with the "
                        "'LoginManager.user_loader' decorator.")
                user = self.user_callback(user_id)
                if user is None:
                    ctx.user = self.anonymous_user()
                else:
                    ctx.user = user
        else:
            ctx.user = user

login_required源码

def login_required(func):
  
    @wraps(func)
    def decorated_view(*args, **kwargs):
        if current_app.login_manager._login_disabled:
            return func(*args, **kwargs)
        elif not current_user.is_authenticated:
            return current_app.login_manager.unauthorized()
        return func(*args, **kwargs)
    return decorated_view

源码链接:Flask_Login

    原文作者:氨基钠
    原文地址: https://www.jianshu.com/p/8772c99ecd1a
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞