Building APIs with Flask and flask_restful in Python

Building robust APIs is crucial for modern web applications, enabling seamless communication between different systems. Python, with its simplicity and versatility, offers powerful tools like Flask and its extension flask_restful, making API development straightforward and efficient.

This article is a continuation of my previous article Flask In Python, where I have explained how to setup Flask in a python application. So, I will not repeat the same here. Let's start with how to use it with flask_restful

Setting Up flask_restful

Firstly, ensure you have Python installed, then install Flask and flask_restful using pip:

pip install Flask flask-restful

Creating a Basic API with Flask

Let’s start with a simple Flask app to understand the fundamentals of building APIs:

from flask import Flask, jsonify

app = Flask(__name__)

@app.route('/hello')
def hello():
    return jsonify({'message': 'Hello, World!'})

if __name__ == '__main__':
    app.run(debug=True)

Accessing http://127.0.0.1:5000/hello in your browser or making a GET request will return a JSON response with the message "Hello, World!"

Utilizing flask_restful for Resource Management

While Flask is excellent for basic routes, flask_restful simplifies handling resources and endpoints.

from flask import Flask
from flask_restful import Api, Resource, reqparse, abort


app = Flask(__name__)
api = Api(app)

users = {}


class Users(Resource):
    def get(self, email):
        return users[email], 200



api.add_resource(Users, "/api/users/<string:email>")


if __name__ == "__main__":
    app.run(debug=True)

The Resource class is the heart of flask_restful. It represents a RESTful resource in your API, encapsulating the logic for handling different HTTP methods (GET, POST, PUT, DELETE, etc.) on a specific endpoint.

By defining a class that inherits from Resource, you can implement HTTP methods like get, post, put, and others. Each method corresponds to an HTTP request type and allows you to define the behavior of your API endpoints for these requests.

Adding reqparse

reqparse is a part of flask_restful that simplifies the parsing and validation of request data. It enables you to define the structure of incoming requests, specifying required parameters, their types, default values, and more. This helps in extracting data from requests and ensures that the data is in the expected format.

With reqparse, you can access query parameters, form data, JSON payload, and other parts of an HTTP request and validate them according to your defined rules. This helps in handling various edge cases and ensures that your API receives the correct data.

from flask import Flask
from flask_restful import Api, Resource, reqparse, abort


app = Flask(__name__)
api = Api(app)

users = {}

users_put_args = reqparse.RequestParser()
users_put_args.add_argument(
    "name", type=str, help="Name is required", required=True)
users_put_args.add_argument(
    "age", type=int, help="Age is required", required=True)
users_put_args.add_argument(
    "gender", type=str, help="Gender is required", required=True)




class Users(Resource):
    def get(self, email):
        return users[email], 200

    def put(self, email):
        abort_if_email_already_exists(email)
        args = users_put_args.parse_args()
        users[email] = args
        return users[email], 201

    def delete(self, email):
        del users[email]
        return "User deleted successfully", 204


api.add_resource(Users, "/api/users/<string:email>")


if __name__ == "__main__":
    app.run(debug=True)

Error Handling with abort

Error handling is a critical aspect of any API. abort is a function provided by Flask that allows you to return HTTP error responses with specific status codes. It interrupts the normal flow of execution when called, allowing you to respond with appropriate error messages and status codes for different situations.

By using abort, you can gracefully handle errors such as invalid requests, missing parameters, unauthorized access, and more. It helps in communicating errors clearly to API consumers, aiding in debugging and providing helpful information on what went wrong.

from flask import Flask
from flask_restful import Api, Resource, reqparse, abort


app = Flask(__name__)
api = Api(app)

users = {}

users_put_args = reqparse.RequestParser()
users_put_args.add_argument(
    "name", type=str, help="Name is required", required=True)
users_put_args.add_argument(
    "age", type=int, help="Age is required", required=True)
users_put_args.add_argument(
    "gender", type=str, help="Gender is required", required=True)


def abort_if_email_already_exists(email):
    if email in users:
        abort(409, message="This email already exists..")


def abort_if_email_does_not_exists(email):
    if email not in users:
        abort(404, message="Email does not exist..")


class Users(Resource):
    def get(self, email):
        abort_if_email_does_not_exists(email)
        return users[email], 200

    def put(self, email):
        abort_if_email_already_exists(email)
        args = users_put_args.parse_args()
        users[email] = args
        return users[email], 201

    def delete(self, email):
        abort_if_email_does_not_exists(email)
        del users[email]
        return "User deleted successfully", 204


api.add_resource(Users, "/api/users/<string:email>")


if __name__ == "__main__":
    app.run(debug=True)

I also created another notebook with sample http requests to handle the methods created above. atatching it to the post.

Conclusion

Flask and flask_restful combine simplicity and power, providing an excellent framework for building APIs in Python. Understanding these fundamental features – handling resources, request parsing, and error handling – lays a solid foundation for creating robust and efficient APIs.

Explore further, experiment with different functionalities, and delve deeper into Flask's and flask_restful's capabilities to craft APIs tailored to your application's needs.


Similar Articles