Extending Flask with Blueprints Explained
Key Concepts
- Blueprints
- Modular Applications
- Registering Blueprints
- URL Prefixing
- Template Inheritance
- Static Files
- Error Handlers
- Subdomains
- Organizing Blueprints
- Testing Blueprints
Blueprints
Blueprints are a way to organize a Flask application into smaller, reusable components. They allow you to define routes, views, and other application logic in a modular way, which can then be registered with the main application.
from flask import Blueprint bp = Blueprint('example', __name__) @bp.route('/') def home(): return 'Hello, World!'
Modular Applications
Modular applications are built by breaking down the application into smaller, manageable parts. Blueprints help achieve this by allowing you to define different parts of the application in separate files or modules.
# module1.py from flask import Blueprint bp1 = Blueprint('module1', __name__) @bp1.route('/module1') def module1_view(): return 'Module 1' # module2.py from flask import Blueprint bp2 = Blueprint('module2', __name__) @bp2.route('/module2') def module2_view(): return 'Module 2'
Registering Blueprints
Once you have defined your blueprints, you need to register them with the main Flask application. This is done using the register_blueprint
method.
from flask import Flask from module1 import bp1 from module2 import bp2 app = Flask(__name__) app.register_blueprint(bp1) app.register_blueprint(bp2)
URL Prefixing
URL prefixing allows you to add a common prefix to all routes defined in a blueprint. This is useful for organizing routes under a specific namespace.
app.register_blueprint(bp1, url_prefix='/api') app.register_blueprint(bp2, url_prefix='/api')
Template Inheritance
Blueprints can have their own templates, which can inherit from the main application's templates. This allows for consistent design across different parts of the application.
# blueprint_templates/base.html <html> <head> <title>{% block title %}{% endblock %}</title> </head> <body> {% block content %}{% endblock %} </body> </html> # blueprint_templates/index.html {% extends "base.html" %} {% block title %}Home{% endblock %} {% block content %} <h1>Welcome to the Home Page</h1> {% endblock %}
Static Files
Blueprints can also serve static files, such as CSS, JavaScript, and images. This is done by specifying a static folder when creating the blueprint.
bp = Blueprint('example', __name__, static_folder='static')
Error Handlers
Blueprints can define their own error handlers, which will be used when an error occurs within the blueprint's routes.
@bp.errorhandler(404) def not_found(error): return 'Not Found', 404
Subdomains
Blueprints can be associated with specific subdomains, allowing you to create multi-tenant applications where different parts of the application are served from different subdomains.
app.register_blueprint(bp1, subdomain='admin') app.register_blueprint(bp2, subdomain='user')
Organizing Blueprints
Blueprints can be organized into packages, making it easier to manage large applications. Each package can contain its own blueprints, templates, and static files.
# myapp/blueprints/admin/__init__.py from flask import Blueprint bp = Blueprint('admin', __name__, template_folder='templates') # myapp/blueprints/user/__init__.py from flask import Blueprint bp = Blueprint('user', __name__, template_folder='templates')
Testing Blueprints
Blueprints can be tested independently of the main application. This allows for more focused and efficient testing of different parts of the application.
import unittest from myapp.blueprints.admin import bp as admin_bp class TestAdminBlueprint(unittest.TestCase): def setUp(self): self.app = Flask(__name__) self.app.register_blueprint(admin_bp) self.client = self.app.test_client() def test_admin_home(self): response = self.client.get('/admin/') self.assertEqual(response.status_code, 200) self.assertIn(b'Admin Home', response.data)