Implement An API Blueprint In Flask

Now that we have a solid understanding of the REST API architecture, it is time to start implementing one on a project. In the Overview article, you saw the end project, fully built with API developed for it. However, to help you learn how it was built, we will start from the bottom. I have already created a basic chat application that you can refer to as you go through this article. To compare your work with the article's final code, refer to v3.0.0-api-blueprint release on GitHub.

For your reference, these are the topics in our discussion:



Table Of Content

This article is broken down into the following subsections:



Overview

In the linked basic chat application (v1.0.0-basic-app above), no blueprints have been used. A blueprint is a logical structure that represents a subset of an application. For example, instead of bundling everything in routes.py, we can choose to separate the logic into auth for authentication-related features or errors for error-related features. Check out the v2.0.0-blueprint release. Why use a blueprint? Blueprints are fantastic for larger applications. Should I ever want to scale this application, a new project structure utilizing blueprints would be suitable.



Create An API Blueprint

To create an api blueprint, let us start by creating an empty folder called api in the app/ sub-directory.

(venv)$ mkdir app/api
# I am running this command from the application's root directory

Create a new file called __init__.py in the new directory:

(venv)$ touch  app/api/__init__.py

Update this new file with the following initialization:

app/api/__init__.py: Initialize the API blueprint

from flask import Blueprint

bp = Blueprint('api', __name__)

from app.api import users, errors, tokens, posts

The last line requires us to create the four files (also known as modules -- they do not exist yet). They are imported at the bottom to avoid circular dependency errors.

(venv)$ cd app
(venv)app$ touch users errors tokens posts

The gist of our API is going to be in the app/api/users.py and app/api/posts.py modules.



Users Resources

To begin with the app/api/users.py module, these are the endpoints we are going to create and work with:

HTTP Method Resource URL Description
GET /api/users/user_id Return a user based on their id
GET /api/users Return a collection of users
POST /api/users Create a new user account
PUT /api/users/user_id Modify a user of id

The API endpoints for users are going to be as follows (skeleton):

app/api/users.py: User API resources

from app.api import bp


@bp.route('/users/<int:id>', methods=['GET'])
def get_user(id):
    pass


@bp.route('/users', methods=['GET'])
def get_users():
    pass


@bp.route('/users', methods=['POST'])
def create_user():
    pass


@bp.route('/users/<int:id>/', methods=['PUT'])
def update_user(id):
    pass


Posts Resources

The endpoints that we are going to work with on the app/api/posts.py module are as follows:

HTTP Method Resource URL Description
GET /api/posts/post_id Return a post based on its id
GET /api/posts Return a collection of posts
POST /api/posts Create a new post
PUT /api/posts/post_id Modify the post of id

The API endpoints for posts are going to be as follows (skeleton):

app/api/posts.py: Posts API resources

from app.api import bp


@bp.route('/posts/<int:id>', methods=['GET'])
def get_post(id):
    pass


@bp.route('/posts', methods=['GET'])
def get_posts():
    pass


@bp.route('/posts', methods=['POST'])
def create_post():
    pass


@bp.route('/posts/<int:id>', methods=['PUT'])
def update_post(id):
    pass


@bp.route('/posts/<int:id>', methods=['DELETE'])
def update_post(id):
    pass

Something about the posts APIs is that the posts have to be linked to a user. For example, in the POST method (while working with posts APIs), we need to ensure that a post is made by a logged-in user identified by their id. This post will be associated with them. Similarly, when interacting with a post (say to update or delete one), a logged-in user can only do so to posts they have authored.



Errors Module

We can define a few helper functions to deal with error responses. To begin, let us add the following:

app/api/errors.py: Deal with error responses

def bad_request():
    pass


Tokens Module

This is where the authentication subsystem is going to be defined. We will provide an alternative way for clients who are not web browsers to log in.

app/api/tokens.py: API authentication module

def get_token():
    pass


def revoke_token():
    pass


Register API Blueprint With The Factory Function

Finally, to complete the setup process, we can now register the API blueprint with the application factory function:

app/api/__init__.py: Register API blueprint with factory function

# ...

def create_app(config_class=Config):
    app = Flask(__name__)

    # ...

    from app.api import bp as api_bp
    app.register_blueprint(api_bp, url_prefix='/api')

    # ...



Share

If you enjoyed this article, you can share it with another person.

Newsletter Subcription

Level up your skills.

We take your privacy seriously. Read our privacy policy. Unsubscribe | Resubscribe.


Comments (0)