In a Python/Flask application, I have defined this endpoint that I expect to return 404 if a client tries to get an id that doesn't exist on my database.
For example:
@app.route('/plants/<int:plant_id>', methods=['GET'])
def get_plant(plant_id):
try:
plant = Plant.query.filter(Plant.id == plant_id).one_or_none()
if plant is None:
abort(404)
return jsonify({
'success': True,
'plant': plant.format()
})
except:
abort(422)
The problem is that when I try to execute it, it always seems to raise an exception and returns 422.
If I remove the try/except syntax, it works as expected and returns the 404. But I lose the capacity of handling exceptions... so it's not a solution for me.
Why am I doing wrong? How could I correctly trigger 404 without setting 404 as the except return?
Thanks!!
Ok, finally I was able to understand it and solve it. I post my findings here so maybe it could help someone in the future. :)
The answer is very basic, actually: every time I abort, I trigger an exception. So, when I aborted, no matter the status code I used, I fell into my except statement, which was returning 422 by default.
What I did to solve it was to implement a custom RequestError, and every time I have a controlled error, I trigger my custom error, which output I can control separately.
This is the implementation of my custom error:
class RequestError(Exception):
def __init__(self, status):
self.status = status
def __str__(self):
return repr(self.status)
And I've changed my route implementation for something like this: (note that I'm now handling first the custom error exception, and only then triggering a generic 422 error)
@app.route('/plants/<int:plant_id>', methods=['GET'])
def get_plant(plant_id):
try:
plant = Plant.query.filter(Plant.id == plant_id).one_or_none()
if plant is None:
raise RequestError(404)
return jsonify({
'success': True,
'plant': plant.format()
})
except RequestError as error:
abort(error.status)
except:
abort(422)
And that does it! \o/