Flask-RESTful API: multiple and complex endpoints

Viewed 50797

In my Flask-RESTful API, imagine I have two objects, users and cities. It is a 1-to-many relationship. Now when I create my API and add resources to it, all I can seem to do is map very easy and general URLs to them. Here is the code (with useless stuff not included):

class UserAPI(Resource):  # The API class that handles a single user
  def __init__(self):
    # Initialize

  def get(self, id):
    # GET requests

  def put(self, id):
    # PUT requests

  def delete(self, id):
    # DELETE requests

class UserListAPI(Resource):  # The API class that handles the whole group of Users
  def __init__(self):

  def get(self):

  def post(self):

api.add_resource(UserAPI, '/api/user/<int:id>', endpoint='user')
api.add_resource(UserListAPI, '/api/users/', endpoint='users')

class CityAPI(Resource):
  def __init__(self):

  def get(self, id):

  def put(self, id):

  def delete(self, id):

class CityListAPI(Resource):
  def __init__(self):

  def get(self):

  def post(self):

api.add_resource(CityListAPI, '/api/cities/', endpoint='cities')
api.add_resource(CityAPI, '/api/city/<int:id>', endpoint='city')

As you can see, I can do everything I want to implement a very basic functionality. I can GET, POST, PUT, and DELETE both objects. However, my goal is two-fold:

(1) To be able to request with other parameters like city name instead of just city id. It would look something like:
api.add_resource(CityAPI, '/api/city/<string:name>', endpoint='city')
except it wouldn't throw me this error:

AssertionError: View function mapping is overwriting an existing endpoint function

(2) To be able to combine the two Resources in a Request. Say I wanted to get all the users associated with some city. In REST URLs, it should look something like:
/api/cities/<int:id>/users

How do I do that with Flask? What endpoint do I map it to?

Basically, I'm looking for ways to take my API from basic to useful.

2 Answers

you can do the id/name thing without duplicating the resource:

api.add_resource(CitiesByNameAPI, '/api/cities/<name_or_id>', endpoint = 'cities_by_name')

class CitiesByNameAPI(Resource):
    def get(self, name_or_id):
        if name_or_id.isdigit():
            city = CityModel.find_by_id(name_or_id)
        else:
            city = CityModel.find_by_name(name_or_id)

        if city:
            return city.to_json(), 200
        return {'error': 'not found'}, 404

not sure if there are any negative effects from this.

Related