AssertionError:视图函数映射覆盖现有端点函数:main

Kim*_*mmy 64 python flask

有没有人知道为什么我不能覆盖现有的端点函数,如果我有这样的两个网址规则

app.add_url_rule('/',
                 view_func=Main.as_view('main'),
                 methods=["GET"])

app.add_url_rule('/<page>/',
                 view_func=Main.as_view('main'),
                 methods=["GET"])
Run Code Online (Sandbox Code Playgroud)

追溯:

Traceback (most recent call last): 
  File "demo.py", line 20, in <module> methods=["GET"]) 
  File ".../python2.6/site-packages/flask??/app.py", 
    line 62, in wrapper_func return f(self, *args, **kwargs) 
  File ".../python2.6/site-packages/flask??/app.py", 
    line 984, in add_url_rule 'existing endpoint function: %s' % endpoint)  
AssertionError: View function mapping is overwriting an existing endpoint 
    function: main
Run Code Online (Sandbox Code Playgroud)

Roe*_*umi 65

同样的问题发生在我身上,但有不同的用法.当我尝试用2个装饰器包装API函数时:

  1. @ app.route()
  2. 我的服装@exception_handler装饰

我得到了同样的异常,因为我试图用这两个装饰器包装多个函数:

@app.route("/path1")
@exception_handler
def func1():
    pass

@app.route("/path2")
@exception_handler
def func2():
    pass
Run Code Online (Sandbox Code Playgroud)

具体来说,它是通过尝试使用名称包装器注册一些函数引起的:

def exception_handler(func):
  def wrapper(*args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        error_code = getattr(e, "code", 500)
        logger.exception("Service exception: %s", e)
        r = dict_to_json({"message": e.message, "matches": e.message, "error_code": error_code})
        return Response(r, status=error_code, mimetype='application/json')
  return wrapper
Run Code Online (Sandbox Code Playgroud)

更改函数的名称为我解决了它(wrapper.func_name = func.func_name):

def exception_handler(func):
  def wrapper(*args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        error_code = getattr(e, "code", 500)
        logger.exception("Service exception: %s", e)
        r = dict_to_json({"message": e.message, "matches": e.message, "error_code": error_code})
        return Response(r, status=error_code, mimetype='application/json')
  # Renaming the function name:
  wrapper.__name__ = func.__name__
  return wrapper
Run Code Online (Sandbox Code Playgroud)

然后,装饰多个端点工作.

  • 您也可以使用[`functools.wraps`](https://docs.python.org/2/library/functools.html#functools.wraps)来实现重命名功能. (16认同)
  • 我不得不使用`wrapper .__ name__`而不是`wrapper.func_name`.也许这是python2和python3之间的区别? (4认同)
  • 这是我使用装饰器的flask restful API 中的问题。`wrapper.__name__ = func.__name__` 在调用 wrapper 之前解决了这个问题。 (2认同)

Mic*_*vis 54

您的视图名称必须是唯一的,即使它们指向相同的视图方法.

app.add_url_rule('/',
                 view_func=Main.as_view('main'),
                 methods = ['GET'])

app.add_url_rule('/<page>/',
                 view_func=Main.as_view('page'),
                 methods = ['GET'])
Run Code Online (Sandbox Code Playgroud)


Uri*_*lit 17

对于使用@ app.route的用户,最好使用key-argument endpoint而不是__name__Roei Bahumi所说的那样修改值.以他的榜样为例:

@app.route("/path1", endpoint='func1')
@exception_handler
def func1():
    pass

@app.route("/path2", endpoint='func2')
@exception_handler
def func2():
    pass
Run Code Online (Sandbox Code Playgroud)

  • 这是一个很好的答案。我只想指出,不需要提供与实际函数名称相同的端点。您可以在端点中放置任何内容,只要不发生冲突即可。前任。我遇到一种情况,我使用高阶函数生成一个函数(3 次),并且我还必须生成端点名称以保持它们唯一。 (2认同)

Mat*_*rna 14

在上面添加@wraps(f)包装函数解决了我的问题。

def list_ownership(f):
    @wraps(f)
    def decorator(*args,**kwargs):
        return f(args,kwargs)
    return decorator
Run Code Online (Sandbox Code Playgroud)


dth*_*dor 8

Flask要求您将单个"视图函数"与"端点"相关联.您正在调用Main.as_view('main')两次,这会创建两个不同的功能(功能完全相同但内存签名不同).简短的故事,你应该干脆做

main_view_func = Main.as_view('main')

app.add_url_rule('/',
             view_func=main_view_func,
             methods=["GET"])

app.add_url_rule('/<page>/',
             view_func=main_view_func,
             methods=["GET"])
Run Code Online (Sandbox Code Playgroud)


The*_*eIT 7

我只想为此添加更多的“模板”类型的解决方案。

def func_name(f):
    def wrap(*args, **kwargs):
        if condition:
            pass
        else:
            whatever you want
        return f(*args, **kwargs)
    wrap.__name__ = f.__name__
    return wrap
Run Code Online (Sandbox Code Playgroud)

我想添加一条非常有趣的文章“ Demystifying Decorators”(我最近发现):https : //sumit-ghosh.com/articles/demystifying-decorators-python/


小智 6

对我来说,这个问题来自于我一年前编写的基本 api 中使用的Flask-jwt-extended(版本 4.xx 及更高版本)的(破坏性)更新,现在我正在将其合并到一个项目中。

@jwt_required 到 @jwt_required()


小智 5

当您在不同的路由上具有相同的函数名称时,也会发生这种情况。