Search code examples
pythonflaskswaggerflask-restplus

Python REST API Numeric Type Route Parameter Issues


I'm starting a new project in Python to aid me helping to learn the language. I'm a C# developer and very comfortable with REST APIs, but I feel I'm missing something in Python. I am writing this with Flask-RESTPlus and have been following examples to get it working. As it currently stands, I do have a working API, but I'm trying to figure this one last piece out.

I need to be able to create an API endpoint that accepts a numeric route parameter, regardless of whether it's an int of a float.

I can get my API working properly if I add multiple routes, but there has to be a better way.

One of my endpoints:

ns_area = Namespace('Area', description='Area calculations')
@ns_area.route('/Acre/<float:input>/ToSquareFoot')
class ConversionsArea(Resource):
    def get(self, input):
        input = float(input)
        return area.acre_to_ft2(input)

This returns a proper calculation

curl -X GET "http://127.0.0.1:5000/api/v1/Area/Acre/1.2/ToSquareFoot" -H "accept: application/json"

This returns a 404 because the route parameter isn't a floating point number

curl -X GET "http://127.0.0.1:5000/api/v1/Area/Acre/1/ToSquareFoot" -H "accept: application/json"

Also, if I don't have a type identifier, it defaults to a string.

I'd really rather not have to duplicate routes like this.

ns_area = Namespace('Area', description='Area calculations')
@ns_area.route('/Acre/<float:input>/ToSquareFoot')
@ns_area.route('/Acre/<int:input>/ToSquareFoot')
class ConversionsArea(Resource):
    def get(self, input):
        input = float(input)
        return area.acre_to_ft2(input)


Solution

  • You can use string in path and evaluate can it be converted to float. If not, raise ValueError and print proper message.

    ns_area = Namespace('Area', description='Area calculations')
    @ns_area.route('/Acre/<string:input>/ToSquareFoot')
    class ConversionsArea(Resource):
        def get(self, input):
            try:
                input = float(input)
                return area.acre_to_ft2(input), 200
            except ValueError:
                return "Can't convert {} to number".format(input), 400