V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
fatea
V2EX  ›  Python

flask 检验是否已经登录的代码,为什么写在函数内部一切正常,用装饰器后出错?

  •  
  •   fatea · 2016-02-18 21:39:59 +08:00 · 6269 次点击
    这是一个创建于 2991 天前的主题,其中的信息可能已经有所发展或是发生改变。

    请问这是为什么呢?
    13 条回复    2016-02-19 00:15:01 +08:00
    Kilerd
        1
    Kilerd  
       2016-02-18 21:55:17 +08:00
    1. current_user 默认都不是 None
    2. is_authenticated => is_authenticated() 这是一个函数。

    至于你说的 问题, 草草看一眼没看出来
    fatea
        2
    fatea  
    OP
       2016-02-18 22:44:48 +08:00
    @Kilerd 1. 谢谢~ 2.在最新的 flask_login 里, is_authenticated 已经变成了 bool 了。
    问题很奇怪,而且估计不是 装饰器的问题,哪怕在函数内部,也要先判断 flask.request.method ,否则还是一样的错误
    mianju
        3
    mianju  
       2016-02-18 22:54:16 +08:00
    使用 flask-login 这个了么?
    Kilerd
        4
    Kilerd  
       2016-02-18 23:06:30 +08:00
    @fatea flask-login 不是自带登陆检测装饰器吗?

    from flask_login import login_required


    以下是他的代码:
    ''' python
    def login_required(func):
    '''
    If you decorate a view with this, it will ensure that the current user is
    logged in and authenticated before calling the actual view. (If they are
    not, it calls the :attr:`LoginManager.unauthorized` callback.) For
    example::

    @app.route('/post')
    @login_required
    def post():
    pass

    If there are only certain times you need to require that your user is
    logged in, you can do so with::

    if not current_user.is_authenticated:
    return current_app.login_manager.unauthorized()

    ...which is essentially the code that this function adds to your views.

    It can be convenient to globally turn off authentication when unit testing.
    To enable this, if the application configuration variable `LOGIN_DISABLED`
    is set to `True`, this decorator will be ignored.

    :param func: The view function to decorate.
    :type func: function
    '''
    @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
    '''


    BTW , is_authenticated 只是你的用户 ORM 模型里面的一个函数,用来验证是否用户通过验证罢了,并不是 boolean

    ` current_user = LocalProxy(lambda: _get_user()) `

    根据你的设置,只想到你的用户 ORM 模型

    所以 ` current_user.is_authenticated ` 就应该是自己设置的。 当然如果你不需要用到这个字段,设置成 boolean 或者 True 也是可以得。

    未登录的使用 可以用

    `if not current_user.is_authenticated(): pass `
    Kilerd
        5
    Kilerd  
       2016-02-18 23:07:29 +08:00
    上面的代码看不清楚,请移至 markdown 编辑器中查看,懒得用 gist 了
    fatea
        6
    fatea  
    OP
       2016-02-18 23:27:10 +08:00
    @Kilerd 嗯...我需要的 是 "未登录状态的检测", login_required 肯定不是用在这儿的嘛。
    对于另一个问题, Since 0.3.0, Flask-Login has set is_active, is_authenticated, is_anonymous to property in UserMixin 。可以看到你贴出来的代码里也是`if not current_user.is_authenticated:`

    抛开上面的细节... 其实最后的问题就是:

    为什么 if current_user.is_authenticated: 不能在函数的入口处使用,而只能在 request.method == 'GET'之后使用?

    补充下:刚才发现,在 request.method == 'POST'情况下, if current_user.is_authenticated 还是会出一样的错。

    然后我在多处打 log(Node.js 的习惯...console.log()),发现了原因:

    在刚接受到 POST 请求, current_user.is_authenticated 就 为 True ,所以根本没有执行之后的登录就返回了。
    fatea
        7
    fatea  
    OP
       2016-02-18 23:27:51 +08:00
    @Kilerd 虽然发现了原因...但是并不明白为什么 T_T
    Kilerd
        8
    Kilerd  
       2016-02-18 23:35:29 +08:00
    @fatea 未登录的可以自己写一个装饰器啊。

    def require_not_login(func):
    @wraps(func)
    ----def decorated_view(*args, **kwargs):
    --------if not current_user.is_authenticated():
    ------------return func(*args, **kwargs)
    --------else:
    ------------flash(_"you must log out before doing this.", "error")
    ------------return redirect(url_for("..."))
    fatea
        9
    fatea  
    OP
       2016-02-18 23:37:17 +08:00
    @Kilerd 这样写报错了所以我来求助的嘛.... 一言以蔽之,就是不能让 if not current_user.is_authenticated 处理 POST 请求,否则出错。
    Kilerd
        10
    Kilerd  
       2016-02-18 23:39:36 +08:00   ❤️ 1
    把你的 用户模型 和 关于 flask_login 的代码贴出来。
    fatea
        11
    fatea  
    OP
       2016-02-18 23:47:08 +08:00
    fatea
        12
    fatea  
    OP
       2016-02-19 00:01:40 +08:00
    @Kilerd 那个 login_manager.request_loader 在这里应该没有用吧?因为我判断登录都是 session 来的,而且 log 表示也没有用到它
    fatea
        13
    fatea  
    OP
       2016-02-19 00:15:01 +08:00
    @Kilerd 我解决了。。。的确是 login_manager.request_loader 的原因,所有的 request 都会经过它,导致的错误,把它注释掉就正常了,装饰器什么的也正常不受影响。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5432 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 28ms · UTC 07:44 · PVG 15:44 · LAX 00:44 · JFK 03:44
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.