【问题标题】:Flask Custom Role Wrapper gives "AssertionError: View function mapping is overwriting an existing endpoint function: run"Flask Custom Role Wrapper 给出“AssertionError:视图函数映射正在覆盖现有端点函数:运行”
【发布时间】:2019-11-14 15:07:34
【问题描述】:

我正在尝试创建一个角色包装器,它允许我为不同的用户限制某些页面和内容。我已经实现了检查这个的方法,但是实现这个的包装器/装饰器失败了,有时也没有,我不知道原因可能是什么。

我已经四处寻找导致此问题的确切原因,但不幸的是,Flask 的回溯并没有像我提出的大多数其他搜索那样给出确凿的原因或解决方案。

我正在使用 Flask-Login、Flask-Migrate 和 Flask-SQLAlchemy 来管理我的 Web 应用程序,我研究了应用 RBAC 的不同方法,但它们都需要对我的数据库模型进行看似复杂的更改,而且我觉得我的方法从长远来看会有更高的工作机会。

这是我的简化代码(如果需要,我可以提供完整的应用程序)。下面是调试器的完整回溯。

谢谢。

routes.py

def require_role(roles=["User"]):
    def wrap(func):
        def run(*args, **kwargs):
            if current_user.is_authenticated:
                if current_user.has_roles(roles):
                    return func(*args, **kwargs)
            return abort(401)
        return run
    return wrap

@app.route('/hidden<id>/history')
@login_required
@require_role(roles=['Admin'])
def hidden_history(id):
    if not validate_id(id):
        return '<span style="color: red;">error:</span> bad id'
    return render_template('hidden_history.html')

@app.route('/hidden<id>/help')
@login_required
def hidden_help(id):
    if not validate_id(id):
        return '<span style="color: red;">error:</span> bad id'
    return render_template('hidden_help.html')

@app.route('/hidden<id>/')
@login_required
@require_role(roles=['Hidden'])
def hidden(id):
    if not validate_id(id):
        return '<span style="color: red;">error:</span> bad id'
    # ...
    return render_template('hidden.html')

Traceback (most recent call last)

Traceback (most recent call last):
  File "A:\Programming\Python\Flask\xevion.dev\wsgi.py", line 1, in <module>
    from app import app, db
  File "A:\Programming\Python\Flask\xevion.dev\app\__init__.py", line 18, in <module>
    from app import routes, models
  File "A:\Programming\Python\Flask\xevion.dev\app\routes.py", line 143, in <module>
    @require_role(roles=['Hidden'])
  File "c:\users\xevion\appdata\local\programs\python\python36\lib\site-packages\flask\app.py", line 1251, in decorator
    self.add_url_rule(rule, endpoint, f, **options)
  File "c:\users\xevion\appdata\local\programs\python\python36\lib\site-packages\flask\app.py", line 67, in wrapper_func
    return f(self, *args, **kwargs)
  File "c:\users\xevion\appdata\local\programs\python\python36\lib\site-packages\flask\app.py", line 1222, in add_url_rule
    'existing endpoint function: %s' % endpoint)
AssertionError: View function mapping is overwriting an existing endpoint function: run

编辑:我现在意识到,当对包装函数的调用不止一次时,它就不起作用了。怎么会?

【问题讨论】:

    标签: python flask wrapper rbac flask-login


    【解决方案1】:

    因此,为了解决过去几个小时一直困扰我的问题,我研究了 flask_login 模块的实际工作原理,经过一番调查,我发现他们使用了 import from functoolswraps

    我导入了它,复制了 flask_login 的基本实现方式,我的应用现在可以运行了。

    def require_role(roles=["User"]):
        def wrap(func):
            @wraps(func)
            def decorated_view(*args, **kwargs):
                if current_user.is_authenticated:
                    if current_user.has_roles(roles):
                        return func(*args, **kwargs)
                return abort(401)
            return decorated_view
        return wrap
    

    flask_login/utils.py#L264

    【讨论】:

    • 感谢分享!我的装饰器中缺少这个wraps。你救了我一整晚!
    【解决方案2】:

    乍一看,这似乎与您在 require_role 装饰器 (docs) 中的 run 函数发生冲突:

    def require_role(roles=["User"]):
        def wrap(func):
            def wrapped_func(*args, **kwargs):
                ...
    

    【讨论】:

    • 更改run函数的名称不会做任何事情,错误不会改变; AssertionError: View function mapping is overwriting an existing endpoint function: wrapped_func :(
    猜你喜欢
    • 1970-01-01
    • 2015-05-03
    • 2021-08-08
    • 1970-01-01
    • 2013-06-19
    • 2020-10-19
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    相关资源
    最近更新 更多