In the first part of this three-part tutorial series, we saw how to write RESTful APIs all by ourselves using Flask as the web framework. In the second part, we created a RESTful API using Flask-Restless which depends on SQLAlchemy as the ORM. In this part, we will use another Flask extension, Flask-Restful, which abstracts your ORM and does not make any assumptions about it.
I will take the same sample application as in the last part of this series to maintain context and continuity. Although this example application is based on SQLAlchemy itself, this extension can be used along with any ORM in a similar fashion, as shown in this tutorial.
Installing Dependencies
While continuing with the application from the first part, we need to install only one dependency:
$ pip install Flask-Restful
The Application
Before we start, you might want to remove the code that we wrote for the second part of this tutorial series for more clarity.
As always, we will start with changes to our application’s configuration, which will look something like the following lines of code:
flask_app/my_app/__init__.py
from flask.ext.restful import Api api = Api(app)
Just adding the above couple of lines to the existing code should suffice.
flask_app/my_app/catalog/views.py
import json from flask import Blueprint, abort from flask.ext.restful import Resource from flask.ext.restful import reqparse from my_app.catalog.models import Product from my_app import api, db catalog = Blueprint('catalog', __name__) parser = reqparse.RequestParser() parser.add_argument('name', type=str) parser.add_argument('price', type=float) @catalog.route('/') @catalog.route('/home') def home(): return "Welcome to the Catalog Home." class ProductApi(Resource): def get(self, id=None, page=1): if not id: products = Product.query.paginate(page, 10).items else: products = [Product.query.get(id)] if not products: abort(404) res = {} for product in products: res[product.id] = { 'name': product.name, 'price': product.price, } return json.dumps(res) def post(self): args = parser.parse_args() name = args['name'] price = args['price'] product = Product(name, price) db.session.add(product) db.session.commit() res = {} res[product.id] = { 'name': product.name, 'price': product.price, } return json.dumps(res) api.add_resource( ProductApi, '/api/product', '/api/product/<int:id>', '/api/product/<int:id>/<int:page>' )
Most of the code above is self-explanatory. I will highlight a few points, though. The code above seems very similar to the one that we wrote in the first part of this series, but here the extension used does a bunch of behind-the-scenes optimizations and provides a lot more features that can be leveraged.
Here the methods declared under any class that subclasses Resource
are automatically considered for routing. Also, any parameters that we expect to receive along with incoming HTTP calls need to be parsed using reqparse
.
Testing the Application
This application can be tested in exactly the same way as we did in the second part of this tutorial series. I have kept the routing URL the same for the same purpose.
Conclusion
In this last part of this three-part tutorial series on developing RESTful APIs with Flask, we saw how to write ORM-independent RESTful APIs. This wraps up the basics of writing RESTful APIs with Flask in various ways.
There is more that can be learned about each of the methods covered, and you can explore this on your own, using the basics you’ve learned in this series.