This is the third article in which I explore different aspects of writing RESTful APIs using the Flask microframework.

The example RESTful server I wrote before used only Flask as a dependency. Today I will show you how to write the same server using Flask-RESTful, a Flask extension that simplifies the creation of APIs.

The RESTful server

As a reminder, here is the definition of the ToDo List web service that has been serving as an example in my RESTful articles:

HTTP Method

URI

Action

GET

http://[hostname]/todo/api/v1.0/tasks

Retrieve list of tasks

GET

http://[hostname]/todo/api/v1.0/tasks/[task_id]

Retrieve a task

POST

http://[hostname]/todo/api/v1.0/tasks

Create a new task

PUT

http://[hostname]/todo/api/v1.0/tasks/[task_id]

Update an existing task

DELETE

http://[hostname]/todo/api/v1.0/tasks/[task_id]

Delete a task

The only resource exposed by this service is a "task", which has the following data fields:

uri: unique URI for the task. String type.

title: short task description. String type.

description: long task description. Text type.

done: task completion state. Boolean type.

Routing

In my first RESTful server example (source code here) I have used regular Flask view functions to define all the routes.

Flask-RESTful provides a Resource base class that can define the routing for one or more HTTP methods for a given URL. For example, to define a Userresource with GET, PUT and DELETE methods you would write:

The add_resource function registers the routes with the framework using the given endpoint. If an endpoint isn't given then Flask-RESTful generates one for you from the class name, but since sometimes the endpoint is needed for functions such as url_for I prefer to make it explicit.

My ToDo API defines two URLs: /todo/api/v1.0/tasks for the list of tasks, and /todo/api/v1.0/tasks/<int:id> for an individual task. Since Flask-RESTful's Resource class can wrap a single URL this server will need two resources:

In the TaskListAPI resource the POST method is the only one the receives arguments. The title argument is required here, so I included an error message that Flask-RESTful will send as a response to the client when the field is missing. The description field is optional, and when it is missing a default value of an empty string will be used. One interesting aspect of theRequestParser class is that by default it looks for fields in request.values, so the location optional argument must be set to indicate that the fields are coming in request.json.

The request parser for the TaskAPI is constructed in a similar way, but has a few differences. In this case it is the PUT method that will need to parse arguments, and for this method all the arguments are optional, including thedone field that was not part of the request in the other resource.

Now that the request parsers are initialized, parsing and validating a request is pretty easy. For example, note how much simpler the TaskAPI.put() method becomes:

A side benefit of letting Flask-RESTful do the validation is that now there is no need to have a handler for the bad request code 400 error, this is all taken care of by the extension.

Generating Responses

My original REST server generates the responses using Flask's jsonifyhelper function. Flask-RESTful automatically handles the conversion to JSON, so instead of this:

return jsonify({'task': make_public_task(task)})

I can do this:

return{'task': make_public_task(task)}

Flask-RESTful also supports passing a custom status code back when necessary:

return{'task': make_public_task(task)},201

But there is more. The make_public_task wrapper from the original server converted a task from its internal representation to the external representation that clients expected. The conversion included removing the id field and adding a uri field in its place. Flask-RESTful provides a helper function to do this in a much more elegant way that not only generates the uri but also does type conversion on the remaining fields:

The task_fields structure serves as a template for the marshal function. The fields.Uri type is a special type that generates a URL. The argument it takes is the endpoint (recall that I have used explicit endpoints when I registered the resources specifically so that I can refer to them when needed).

Authentication

The routes in the REST server are all protected with HTTP basic authentication. In the original server the protection was added using the decorator provided by the Flask-HTTPAuth extension.

Since the Resouce class inherits from Flask's MethodView, it is possible to attach decorators to the methods by defining a decorators class variable: