108

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

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"])

追溯:

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
4

14 回答 14

151

当我在模块中有多个 API 函数并尝试用 2 个装饰器包装每个函数时,同样的问题也发生在我身上:

  1. @app.route()
  2. 我的自定义 @exception_handler 装饰器

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

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

@app.route("/path2")
@exception_handler
def func2():
    pass

具体来说,这是由于尝试使用名称wrapper注册一些函数引起的:

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

更改函数的名称为我解决了它(wrapper.__name__ = 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

然后,装饰多个端点起作用了。

于 2017-02-15T16:20:30.777 回答
72

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

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'])
于 2013-06-23T01:10:32.783 回答
32

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

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

@app.route("/path2", endpoint='func2')
@exception_handler
def func2():
    pass
于 2017-03-13T14:36:06.777 回答
9

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"])
于 2013-08-04T00:23:47.540 回答
9

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

于 2019-07-01T12:48:04.060 回答
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

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

于 2018-03-09T10:12:53.093 回答
4

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

def list_ownership(f):
    @wraps(f)
    def decorator(*args,**kwargs):
        return f(args,kwargs)
    return decorator
于 2020-10-26T09:01:30.913 回答
1

有一个针对最近引入的 Flask 问题 #570(flask 0.10)的修复,它会导致引发此异常。

https://github.com/mitsuhiko/flask/issues/796

因此,如果您转到 flask/app.py 并注释掉 4 行 948..951,这可能会有所帮助,直到问题在新版本中完全解决。

这种变化的差异在这里:http: //github.com/mitsuhiko/flask/commit/661ee54bc2bc1ea0763ac9c226f8e14bb0beb5b1

于 2013-07-19T11:29:47.763 回答
1

如果您认为您有唯一的端点名称并且仍然给出此错误,那么您可能正面临问题。我的情况也是如此。

如果您有相同的版本,则此问题与烧瓶 0.10 相关,然后执行以下操作以摆脱此问题:

sudo pip uninstall flask
sudo pip install flask=0.9
于 2017-08-28T12:51:57.267 回答
0

即使它们指向相同的视图方法,您的视图名称也必须是唯一的,或者您可以添加 from functools import wraps 并使用 @wraps https://docs.python.org/2/library/functools.html

于 2019-05-30T09:25:47.350 回答
0

使用烧瓶 0.9 而不是使用以下命令 sudo pip uninstall flask

sudo pip install flask==0.9
于 2019-06-06T09:28:30.697 回答
0

如果您在 python 笔记本上使用烧瓶,则每次更改代码时都需要重新启动内核

于 2021-05-04T17:42:19.233 回答
0

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

@jwt_required 到 @jwt_required()

于 2022-01-05T18:39:03.163 回答
0

也许有些东西没有区别

  1. 检查网址
  2. 检查函数名
于 2022-03-03T06:57:37.220 回答