烧瓶装饰器:无法从 URL 传递参数

Posted

技术标签:

【中文标题】烧瓶装饰器:无法从 URL 传递参数【英文标题】:Flask decorator : Can't pass a parameter from URL 【发布时间】:2013-08-21 01:18:57 【问题描述】:

我对烧瓶很陌生,我正在尝试使用装饰器的强大功能:p 我读了很多东西,在这里找到了大量关于 python 装饰器的主题,但没有什么真正有用的。

@app.route('groups/<id_group>')
@group_required(id_group)
@login_required
def groups_groupIndex(id_group):
    #do some stuff
    return render_template('index_group.html')

这是我得到的错误:

@group_required(id_group), NameError: name 'id_group' is not defined

好的,id_group 还没有定义,但我不明白为什么我可以在函数 groups_groupIndex 中使用来自 URL 的 id_group 参数,但不能在装饰器中使用!

我尝试移动/切换装饰器,但每次都出现同样的错误。

这是我的装饰器,但它似乎工作正常

def group_required(group_id):
    def decorated(func):
        @wraps(func)
        def inner (*args, **kwargs):
            #Core_usergroup : table to match users and groups
            groups = Core_usergroup.query.filter_by(user_id = g.user.id).all()
            for group in groups:
                #if the current user is in the group : return func
                if int(group.group_id) == int(group_id) :
                    return func(*args, **kwargs)
            flash(gettext('You have no right on this group'))
            return render_template('access_denied.html')     
        return inner
    return decorated

也许我没有看到我应该看到的装饰器...我可以这样使用我的装饰器还是需要我重写一些不同的东西?

【问题讨论】:

【参考方案1】:

您将group_id 定义为函数参数;这使它成为该函数中的本地名称。

这不会使该名称可用于其他范围;装饰器所在的全局命名空间看不到该名称。

wrapper 函数却可以。调用时,它将从 @apps.route() 包装器传递该参数:

def group_required(func):
    @wraps(func)
    def wrapper(group_id, *args, **kwargs):
        #Core_usergroup : table to match users and groups
        groups = Core_usergroup.query.filter_by(user_id = g.user.id).all()
        for group in groups:
            #if the current user is in the group : return func
            if int(group.group_id) == int(group_id) :
                return func(*args, **kwargs)
        flash(gettext('You have no right on this group'))
        return render_template('access_denied.html')     
    return wrapper

请注意,此装饰器不会将group_id 参数传递给装饰函数;使用 return func(group_id, *args, **kwargs) 而不是您仍然需要在视图函数中访问该值。

【讨论】:

我知道这是范围问题,非常感谢,现在可以正常工作了 :) @anjalis 并且仍将 group_id 作为显式参数传入。 Python 在调用时会从 **... 映射中解压缩参数。如果您的测试失败,那是因为包装器没有将 group_id 传递给视图函数。 @sudocoder: 抱歉,虽然func 确实丢失了,但这里的装饰器明确希望被装饰的函数至少接受一个位置参数group_id。您链接的另一篇文章可能会删除该要求,但这并不是使此装饰器工作的严格要求。如果它对您不起作用,则说明其他问题。

以上是关于烧瓶装饰器:无法从 URL 传递参数的主要内容,如果未能解决你的问题,请参考以下文章

将参数传递给要装饰的类方法的装饰器

将参数从Javascript传递到烧瓶python脚本[重复]

python3 如何给装饰器传递参数

Python 装饰器强制显式传递参数

*args 是向/​​从装饰函数传递参数的正确方法吗?

装饰器参数中无法识别的类