From e68b34eb6c4636f7006a9d4c1172d5d09d6b2dc7 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Sat, 17 Sep 2011 19:39:19 +0200 Subject: [PATCH] Added API example to the method view docs --- docs/views.rst | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/docs/views.rst b/docs/views.rst index 10ddb57d..441620a6 100644 --- a/docs/views.rst +++ b/docs/views.rst @@ -156,3 +156,72 @@ specify a list of decorators to apply in the class declaration:: Due to the implicit self from the caller's perspective you cannot use regular view decorators on the individual methods of the view however, keep this in mind. + +Method Views for APIs +--------------------- + +Web APIs are often working very closely with HTTP verbs so it makes a lot +of sense to implement such an API based on the +:class:`~flask.views.MethodView`. That said, you will notice that the API +will require different URL rules that go to the same method view most of +the time. For instance consider that you are exposing a user object on +the web: + +=============== =============== ====================================== +URL Method Description +--------------- --------------- -------------------------------------- +``/users/`` ``GET`` Gives a list of all users +``/users/`` ``POST`` Creates a new user +``/users/`` ``GET`` Shows a single user +``/users/`` ``PUT`` Updates a single user +``/users/`` ``DELETE`` Deletes a single user +=============== =============== ====================================== + +So how would you go about doing that with the +:class:`~flask.views.MethodView`? The trick is to take advantage of the +fact that you can provide multiple rules to the same view. + +Let's assume for the moment the view would look like this:: + + class UserAPI(MethodView): + + def get(self, user_id): + if user_id is None: + # return a list of users + pass + else: + # expose a single user + pass + + def post(self): + # create a new user + pass + + def delete(self, user_id): + # delete a single user + pass + + def put(self, user_id): + # update a single user + pass + +So how do we hook this up with the routing system? By adding two rules +and explicitly mentioning the methods for each:: + + user_view = UserAPI.as_view('user_api') + app.add_url_rule('/users/', defaults={'user_id': None}, + view_func=user_view, methods=['GET', 'POST']) + app.add_url_rule('/users/', view_func=user_view, + methods=['GET', 'PUT', 'DELETE']) + +If you have a lot of APIs that look similar you can refactor that +registration code:: + + def register_api(view, endpoint, url, pk='id', pk_type='int'): + view_func = view.as_view(endpoint) + app.add_url_rule(url, defaults={pk: None}, + view_func=view_func, methods=['GET', 'POST']) + app.add_url_rule('%s<%s:%s>' % (url, pk), view_func=view_func, + methods=['GET', 'PUT', 'DELETE']) + + register_api(UserAPI, 'user_api', '/users/', pk='user_id')