I have the following Flask routes and a custom helper:
from spots import app, db
from flask import Response
import simplejson as json
def json_response(action_func):
def create_json_response(*args, **kwargs):
ret = action_func(*args, **kwargs)
code = 200
if len(ret) == 2:
code = ret[0]
resp = ret[1]
else:
resp = ret[0]
return Response(
response=json.dumps(resp, indent=4),
status=code,
content_type='application/json'
)
return create_json_response
@app.route('/test')
@json_response
def test():
return 400, dict(result="Test success")
@app.route('/')
@json_response
def home():
return 200, dict(result="Home success")
I would expect a GET request to /test to return something like {"result":"Test success"}
but that is not the case. Instead, any request seems to match the last route, i.e. home
. Why?
I wonder if this is caused by some lack of insulation between the different calls to json_response
?
Thanks in advance.
As Видул Петров said the solution is to use functools.wraps:
import functools
def json_response(action_func):
@functools.wraps(action_func)
def create_json_response(*args, **kwargs):
...
return create_json_response
The reason is that Flask’s routing system maps URLs to "endpoints", and then endpoints to view functions. The endpoint defaults to the __name__
attribute of the view function. In this case the decorated function was passed to app.route
so the endpoint was create_json_response
for both rules and the last view defined for that endpoint was used in both cases.
functools.wraps takes the __name__
(and other attributes) from the original function and fixes this. It is always a good idea to use it in decorated wrappers.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With