Search code examples
pythonflaskroutesflask-restful

Flask + Flask-RESTful: Match specific variables to routes


How can I achieve the following?

# only if model_type in ['a', 'b', 'c']
api.add_resource(FooAPI, '/<string:model_type'>

# only if model_type in ['x', 'y', 'z']
api.add_resource(BarAPI, '/<string:model_type'>

Rather than having the following code:

api.add_resource(FooAAPI, '/a'>
api.add_resource(FooBAPI, '/b'>
api.add_resource(FooCAPI, '/c'>

api.add_resource(BarXAPI, '/x'>
api.add_resource(BarYAPI, '/y'>
api.add_resource(BarZAPI, '/z'>

Solution

  • You can use any converter with your desired path and work with media_type as a variable at the same time:

    api.add_resource(FooAPI, '/<any(a, b, c):model_type>')
    api.add_resource(BarAPI, '/<any(x, y, z):model_type>')
    

    If you want them to be dynamic:

    FooAPIOptions = ['a', 'b', 'c']
    
    api.add_resource(
        FooAPI, "/<any({}):model_type>".format(str(FooAPIOptions)[1:-1]))
    
    

    A simple app would be:

    from flask import Flask
    from flask_restful import Resource, Api
    
    app = Flask(__name__)
    api = Api(app)
    
    
    class FooAPI(Resource):
        def get(self, model_type=None):
            print(model_type) # for example it prints a for "/a" path
            return {'hello': 'world'}
    
    
    FooAPIOptions = ['a', 'b', 'c']
    
    api.add_resource(
        FooAPI, "/<any({}):model_type>".format(str(FooAPIOptions)[1:-1]))
    
    if __name__ == '__main__':
        app.run(debug=True)