Using Blueprint to Organize Flask Apps

sachingeek

Sachin

Posted on November 26, 2023

Using Blueprint to Organize Flask Apps

Introduction

Large applications can become complex and difficult to manage due to the presence of numerous components and intricate structures.

Flask blueprints help in organizing large applications into smaller, manageable components, leading to enhanced maintainability of the application.

Blueprints can contain views, templates, and static files for various components, similar to the structure of a typical Flask application. These blueprints can be registered with the Flask app to integrate them into the application.

Flask App Structure

If you've used the Flask framework before, you might structure your Flask application as follows:

.
├── app.py
├── static/
└── templates/
    └── index.html
Enter fullscreen mode Exit fullscreen mode

After you've created the structure for your app, you'll add some code to the app.py file.

# app.py
from flask import Flask, render_template

app = Flask(__name__)

@app.route("/")
def home():
    return render_template("index.html")
Enter fullscreen mode Exit fullscreen mode

In smaller projects, defining views within the main file may not pose a significant problem. However, in more complex projects, when you need to create routes for various components such as user management, admin functions, profiles, voting, and more, organizing these routes within a single file can become challenging. This can lead to poor code maintainability and make the project harder to manage.

This is precisely where blueprints prove valuable, as they allow you to structure your application into smaller components, enhancing maintainability.

Creating the Blueprint

Add the following code to a new Python file at the root level, blueprint.py.

# blueprint.py
from flask import Blueprint

bp = Blueprint("blueprint", __name__)

@bp.route("/")
def home():
    return "<h1>Hello</h1>"

@bp.route("/user")
def user_info():
    return "<h1>User Info</h1>"
Enter fullscreen mode Exit fullscreen mode

The code imports the Blueprint class from the flask which will help in defining the routes.

The instance of the Blueprint is created by calling Blueprint("blueprint", __name__) and passed in two arguments, first, "blueprint", is the Blueprint's name, and the second, __name__, is the Blueprint's import name. After that, the instance is saved in the bp variable.

The routes are defined using the Blueprint instance (bp) in a similar manner to how routes are defined using the Flask application instance (app).

The @bp.route() decorators are used to associate URL routes with the view functions defined within the blueprint. The home() function is associated with the root URL ("/"), and the user_info() function is associated with the "/user" URL.

Registering the Blueprint

A blueprint is similar to a Flask app, but it is not an app, instead, the blueprint must be registered within the Flask app to extend its functionality.

Navigate to the main Flask app created in the app.py Python file and register the above-created blueprint.

# app.py
from flask import Flask
from blueprint import bp

# Flask app instance
app = Flask(__name__)

app.register_blueprint(bp)

if __name__ == "__main__":
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

The code imports the Blueprint instance, bp, from the blueprint module (blueprint.py), and this import includes all of the blueprint's routes and views.

The register_blueprint() method is then used to register the blueprint instance (bp) with the Flask app instance (app).

If you run the app, you can access the routes defined within the blueprint.

Mounting Blueprints at Different Locations

Blueprints can be attached to a certain URL path that can be prefixed with all of the routes defined within the blueprint.

You can make this happen by using the url_prefix parameter while registering the blueprint using the register_blueprint() method in the Flask app.

# app.py
from flask import Flask
from blueprint import bp

# Flask app instance
app = Flask(__name__)

app.register_blueprint(bp, url_prefix="/demo")

if __name__ == "__main__":
    app.run(debug=True)
Enter fullscreen mode Exit fullscreen mode

The url_prefix is now "/demo". This means that the routes within the blueprint ("/" and "/user") can be accessed by adding "/demo" at the beginning of their URL paths.

The complete URL of the ("/") route is changed to "/demo/" for the home() function. Also, the complete URL of the "/user" route will now be "/demo/user" for the user_info() function.

You can set the url_prefix while making the Blueprint instance. The Blueprint class offers a url_prefix parameter, and the provided code example demonstrates its usage.

# blueprint.py
from flask import Blueprint

bp = Blueprint("blueprint", __name__, url_prefix="/sample")
Enter fullscreen mode Exit fullscreen mode

The URL path for the ("/") route will become "/sample/". Likewise, the URL path for the "/user" route will change to "/sample/user".

Note: If you set the url_prefix parameter inside the blueprint, avoid setting it again during the blueprint registration. Doing so will overwrite the blueprint's URL prefix.

Caution:

If you set url_prefix in the blueprint and then set it again while registering the blueprint within the app, the latter will overwrite the former.

Templates and Static Folders

You have several options for organizing your app using blueprints.

.
└── app/
    ├── __init__.py
    ├── admin/
    │   ├── __init__.py
    │   ├── routes.py
    │   ├── static/
    │   └── templates/
    ├── user/
    │   ├── __init__.py
    │   ├── routes.py
    │   ├── static/
    │   └── templates/
    └── models.py
Enter fullscreen mode Exit fullscreen mode

If your project's structure aligns with the example above, you'll have to indicate the locations of templates and static folders within your Blueprint.

The Blueprint class gives you parameters, templates_folder and static_folder, which allow you to define the exact path (either absolute or relative) to the blueprint's templates and static folder when creating an instance of the Blueprint class.

# admin/routes.py
from flask import Blueprint

admin_bp = Blueprint("admin_blueprint",
                     __name__,
                     template_folder="templates",
                     static_folder="static")
Enter fullscreen mode Exit fullscreen mode
# user/routes.py
from flask import Blueprint

user_bp = Blueprint("user_blueprint",
                    __name__,
                    template_folder="templates",
                    static_folder="static")
Enter fullscreen mode Exit fullscreen mode

Both "admin_bp" and "user_bp" blueprints have their own directories for templates and static files. This separation ensures that their respective templates and assets are kept separate from other parts of the app, maintaining isolation and organization.

Avoid Template Name Clashes

When you're designing blueprints for different parts of your application, the arrangement of your project holds significance. For instance, referring to the layout mentioned above, duplicating HTML filenames in the admin/templates and user/templates directories can lead to naming clashes.

The Flask application searches for templates in the "templates" directory. If there are duplicate template file paths across different blueprints, the one that takes precedence depends on the order of blueprint registration. The one registered later will override the earlier one.

To avoid potential issues, you can shape the project layout in the following manner:

.
└── app/
    ├── app.py
    ├── models.py
    ├── admin/
    │   ├── __init__.py
    │   ├── routes.py
    │   ├── static/
    │   └── templates/
    │       └── admin/
    │           └── index.html
    └── user/
        ├── __init__.py
        ├── routes.py
        ├── static/
        └── templates/
            └── user/
                └── index.html
Enter fullscreen mode Exit fullscreen mode

Alternatively, you can assign distinct names to the templates.

Template Routing with Blueprints

Template routing with blueprints is distinct from the conventional approach. It involves a specific format where the blueprint name is added as a prefix to the associated view function.

As an example, if your blueprint is named admin_blueprint and includes a view function named home(), then the format becomes admin_blueprint.home.

admin/templates/admin/index.html

<a href="{{ url_for('user_blueprint.home') }}">User</a>
Enter fullscreen mode Exit fullscreen mode

The link mentioned above points to the route connected with the home() function in the user_blueprint. The url_for() function dynamically produces a URL for the user_blueprint.home route.

user/templates/user/index.html

<a href="{{ url_for('admin_blueprint.home') }}">Admin</a>
Enter fullscreen mode Exit fullscreen mode

Likewise, the situation is identical to the link mentioned earlier. It leads to the route linked with the home function in the admin_blueprint. The url_for() function dynamically generates a URL for the admin_blueprint.home route.

Including CSS Files with Blueprints: Creating URLs for Static Assets

The procedure is quite similar to what you did with templates. To include or provide CSS files within the HTML template, you should construct a URL that directs to the CSS file situated in the specified static folder of the blueprint.

As an example, the method to link the "style.css" file found in the static directory of the "admin_blueprint" blueprint would be url_for('admin_blueprint.static', filename='style.css').

Note: You must indicate the directory path where static files (CSS, JavaScript, images, etc.) are situated for this blueprint. This is achieved using the static_folder parameter.

admin/templates/admin/index.html

<link rel="stylesheet" href="{{ url_for('admin_blueprint.static', filename='style.css') }}">
Enter fullscreen mode Exit fullscreen mode

This HTML code snippet above uses the url_for() function to generate a URL that points to the "style.css" static file linked to the admin_blueprint.

Custom URL Path for Static Files

Flask Blueprint provides a static_url_path parameter that provides flexibility to define a custom URL prefix for the static files (CSS, JavaScript, images, etc.) associated with the Blueprint.

# admin/routes.py
from flask import Blueprint

admin_bp = Blueprint("admin_blueprint",
                     __name__,
                     template_folder="templates",
                     static_folder='static',
                     static_url_path='admin')
Enter fullscreen mode Exit fullscreen mode

The static_url_path is established as "admin", effectively making the static files within the admin_blueprint accessible under the admin/ URL path.

Now you can directly include static files (CSS, JavaScript, images, etc) by specifying the static URL path.

Including Static Files using Static URL Path

<link rel="stylesheet" href="admin/style.css">

<!--Body Section-->
<img src="admin/partners.png">
Enter fullscreen mode Exit fullscreen mode

The complete webpage would look like the image shown below:

Webpage

Conclusion

A Flask Blueprint is used as an extension for a Flask app, and it serves the purpose of organizing large and complex applications into smaller, more manageable components.

Let's recall what you've seen in this tutorial:

  • What is Blueprint in Flask

  • Creating and Registering a Blueprint

  • Template routing with Blueprint

  • Including static files with Blueprint

  • Custom URL path for static assets


🏆Other articles you might be interested in if you liked this one

Upload and display images on the frontend using Flask in Python.

Building a Flask image recognition webapp using a deep learning model.

How to connect the SQLite database with Flask app using Python?

How to create a database in Appwrite using Python?

How to Integrate TailwindCSS with Flask?

What is context manager and how to use them using with statement?


That's all for now

Keep Coding✌✌

💖 💪 🙅 🚩
sachingeek
Sachin

Posted on November 26, 2023

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related