Reputation: 4059
Does anyone know why I can't overwrite an existing endpoint function if i have two url rules like this
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:
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
Upvotes: 155
Views: 225046
Reputation: 819
Users of FLASK-RESTX:
The error is triggered when we use both api.init_app(app)
and app.register_blueprint()
. Just remove of the two.
app = Flask(__name__)
app.register_blueprint(api, url_prefix='/api/1')
app.run(debug=True)
Calling Api.init_app() is not required here because registering the blueprint with the app takes care of setting up the routing for the application.
https://flask-restx.readthedocs.io/en/latest/scaling.html
Upvotes: 1
Reputation: 31
For those that come here later.
To expand on the comment that ryannjohnson left on this answer.
When you use the @wraps() function from the functools library, as far as I understand, it essentially allows you to achieve the same result as using wrapper.__name__ = func.__name__
except it's more concise and it doesn't require you to manually perform the renaming yourself.
Just wanted to add an answer here to make it easier to find this info for those that might not see the comments and are more focused on the submitted answers.
Upvotes: 0
Reputation: 1
This can also happen if you have selected your debugger as "Python: File" instead of "Python: Flask", making it "Python: Flask" helped me get rid of the said error.
Upvotes: 0
Reputation: 7150
I encountered the same AssertionError, but have not seen a solution here. In my case, I run a decorated function in a Jupyter cell twice, then the error was caused by running an endpoint function with the same name as an existing running endpoint function.
Upvotes: 1
Reputation: 21
I'm working on a similar problem and I managed to get rid of it by returning the wrapper funcion, which wasn't being done before:
def decorator_func(func_to_decorate):
def wrapper_func():
return func_to_decorate
return wrapper_func # I wasn't returning wrapper func!
Upvotes: 2
Reputation: 141
maybe something contains no difference
Upvotes: 2
Reputation: 71
This is issue for me was from an (breaking) update to flask-jwt-extended (version 4.x.x and up) used in a basic api I wrote a year ago and am now incorporating into a project.
@jwt_required to @jwt_required()
Upvotes: 7
Reputation: 91
In case you are using flask on python notebook, you need to restart kernel everytime you make changes in code
Upvotes: 1
Reputation: 621
Adding @wraps(f)
above the wrapper function solved my issue.
def list_ownership(f):
@wraps(f)
def decorator(*args,**kwargs):
return f(args,kwargs)
return decorator
Upvotes: 16
Reputation: 3683
This same issue happened to me when I had more than one API function in the module and tried to wrap each function with 2 decorators:
I got this same exception because I tried to wrap more than one function with those two decorators:
@app.route("/path1")
@exception_handler
def func1():
pass
@app.route("/path2")
@exception_handler
def func2():
pass
Specifically, it is caused by trying to register a few functions with the name 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
Changing the name of the function solved it for me (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
Then, decorating more than one endpoint worked.
Upvotes: 227
Reputation: 357
This can happen also when you have identical function names on different routes.
Upvotes: 20
Reputation: 373
use flask 0.9 instead
use the following commands
sudo pip uninstall flask
sudo pip install flask==0.9
Upvotes: 1
Reputation: 11
Your view names need to be unique even if they are pointing to the same view method, or you can add from functools import wraps and use @wraps https://docs.python.org/2/library/functools.html
Upvotes: 1
Reputation: 518
I would just like to add to this a more 'template' type solution.
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
would just like to add a really interesting article "Demystifying Decorators" I found recently: https://sumit-ghosh.com/articles/demystifying-decorators-python/
Upvotes: 8
Reputation: 3405
If you think you have unique endpoint names and still this error is given then probably you are facing issue. Same was the case with me.
This issue is with flask 0.10 in case you have same version then do following to get rid of this:
sudo pip uninstall flask
sudo pip install flask=0.9
Upvotes: 2
Reputation: 2318
For users that use @app.route it is better to use the key-argument endpoint
rather then chaning the value of __name__
like Roei Bahumi stated. Taking his example will be:
@app.route("/path1", endpoint='func1')
@exception_handler
def func1():
pass
@app.route("/path2", endpoint='func2')
@exception_handler
def func2():
pass
Upvotes: 56
Reputation: 65
There is a fix for Flask issue #570 introduced recenty (flask 0.10) that causes this exception to be raised.
See https://github.com/mitsuhiko/flask/issues/796
So if you go to flask/app.py and comment out the 4 lines 948..951, this may help until the issue is resovled fully in a new version.
The diff of that change is here: http://github.com/mitsuhiko/flask/commit/661ee54bc2bc1ea0763ac9c226f8e14bb0beb5b1
Upvotes: 2
Reputation: 5060
Flask requires you to associate a single 'view function' with an 'endpoint'. You are calling Main.as_view('main')
twice which creates two different functions (exactly the same functionality but different in memory signature). Short story, you should simply do
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"])
Upvotes: 12
Reputation: 2430
Your view names need to be unique even if they are pointing to the same view method.
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'])
Upvotes: 78