9

The following strikes me as inelegant but it works. Is there a way to have flask-restful handle the two standard flavors of get (i.e. get everything and get one item) using the same resource class?

Thanks.

from flask_restful import Resource
# ...

class People(Resource):
    def get(self):
        return [{'name': 'John Doe'}, {'name': 'Mary Canary'}]

class Person(Resource):
    def get(self, id):
        return {'name': 'John Doe'}
# ...

api.add_resource(People, '/api/people')
api.add_resource(Person,  '/api/people/<string:id>')
John Lockwood
  • 3,787
  • 29
  • 27
  • Sorry, but I don't think so. Whenever I tried, I received the "TypeError: get() missing 1 required positional argument" error. It would be nice if the positional argument could be optional, and set to None when it's not passed, but maybe there is a reason it doesn't work that way. – Kelly Keller-Heikkila Sep 06 '15 at 03:52
  • I finally got frustrated enough with it that I tested a Proof of Concept for an alternative implementation -- GIST is here http://bit.ly/1RVzWm9 . I believe, and have said so here: https://github.com/flask-restful/flask-restful/issues/114 that the reason for it is that Flask-Restful followed followed the path of least resistance given the implementation of Flask's add_url_rule. – John Lockwood Jan 02 '16 at 00:17

2 Answers2

12

I think this is what you're looking for:

from flask_restful import Resource
# ...


class People(Resource):

    def get(self, id=None):
        if not id:
            return {'name': 'John Doe'}
        return [{'name': 'John Doe'}, {'name': 'Mary Canary'}]


api.add_resource(People, '/api/people', '/api/people/<id>')

You can put restrictions on the id buy adding it as an argument to the request parser:

parser.add_argument('id', location='view_args', type=..)
kardaj
  • 1,897
  • 19
  • 19
0

Yeah, check out the argument parsing documentation. If needed, this will give you the flexibility to create some logic around the arguments received with the request.

from flask_restful import Api, Resource, reqparse
# ...

api = Api(app)
parser = reqparse.RequestParser()
parser.add_argument('id')

class People(Resource):
def get(self):
    data = parser.parse_args()
    if not data['id']:
        return [{'name': 'John Doe'}, {'name': 'Mary Canary'}]
    else:
        # data lookup using id
        # for example using SQLAlchemy...
        # person = Person.query.filter_by(id = data['id']).first_or_404()
        return {'id': data['id'], 'name': 'John Doe'}

api.add_resource(People, '/api/people')

Then try with:

  • localhost:/api/people
  • localhost:/api/people?id=1
siegerts
  • 461
  • 4
  • 11
  • i think that is not the way how restful is implemented.. imo – rrw Mar 26 '16 at 13:32
  • May not be to REST spec but it's still possible with `flask-restful` – siegerts Mar 26 '16 at 14:16
  • yes, i didnt say its not possible, i see it fine, but im just saying that its not the way it should be implemented if its REST, because some beginners searching and will stumble upon this might think this is the way it should be implemented :) – rrw Mar 26 '16 at 15:00