YouTip LogoYouTip

Flask Blueprints

## Blueprint When an application has only one file, it's acceptable to have all routes written together. But as functionality growsβ€”user module, article module, admin backendβ€”the code can become difficult to maintain. Blueprint is the modular solution provided by Flask, allowing you to split your application into independent functional units. * * * ## Why Blueprints Are Needed Core problems solved by blueprints: * Code Organization: Group related routes, templates, and static files together * Reusability: The same blueprint can be registered to different applications, or registered multiple times (with different prefixes) * Team Collaboration: Different developers can be responsible for different blueprint modules, reducing conflicts ![Image 1: Flask Blueprint Module Architecture](#) * * * ## Creating a Blueprint Blueprints are created using the Blueprint class, with usage very similar to Flaskβ€”same route decorator, same view function writing style: ## Example # File path: auth.py (User Authentication Blueprint) from flask import Blueprint, render_template, request, session, redirect, url_for # Create blueprint instance # First parameter "auth" is the blueprint's name (used for url_for references) # __name__ tells the blueprint where to look for templates and static files bp = Blueprint("auth", __name__) # Use bp.route in the blueprint, not app.route @bp.route("/login", methods=["GET","POST"]) def login(): if request.method=="POST": username = request.form.get("username","") if username: session= username return redirect(url_for("blog.index")) return render_template("auth/login.html") @bp.route("/register", methods=["GET","POST"]) def register(): if request.method=="POST": username = request.form.get("username","") if username: return redirect(url_for("auth.login")) return render_template("auth/register.html") @bp.route("/logout") def logout(): session.clear() return redirect(url_for("blog.index")) ## Example # File path: blog.py (Blog Blueprint) from flask import Blueprint, render_template bp = Blueprint("blog", __name__) @bp.route("/") def index(): # Simulate article data posts =[ {"title": "Flask Getting Started","author": ""}, {"title": "Blueprint Detailed Explanation","author": ""}, ] return render_template("blog/index.html", posts=posts) @bp.route("/create", methods=["GET","POST"]) def create(): return render_template("blog/create.html") * * * ## Registering Blueprints Blueprints don't take effect automatically after creation; they need to be registered in the application: ## Example # File path: app.py from flask import Flask from auth import bp as auth_bp from blog import bp as blog_bp app = Flask( __name__ ) app.secret_key="dev-secret-key" # Register blueprints to the application # url_prefix: Add a uniform prefix to all routes in the blueprint app.register_blueprint(auth_bp, url_prefix="/auth") # auth blueprint routes become: /auth/login, /auth/logout, /auth/register app.register_blueprint(blog_bp) # blog blueprint has no prefix, routes remain: /, /create Complete routing table after registration: | URL | Blueprint | endpoint (used by url_for) | | --- | --- | --- | | / | blog | blog.index | | /create | blog | blog.create | | /auth/login | auth | auth.login | | /auth/register | auth | auth.register | | /auth/logout | auth | auth.logout | > After registering blueprints, the endpoint in url_for() needs to be prefixed with the blueprint name, e.g., url_for("auth.login") instead of url_for("login"). * * * ## Special Usage of url_for in Blueprints Within the same blueprint, you can use relative references starting with a dot: ## Example # Inside auth.py, using relative references is more concise @bp.route("/") def index(): # Relative reference within the same blueprint (starts with .) login_url = url_for(".login")# Equivalent to url_for("auth.login") register_url = url_for(".register")# Equivalent to url_for("auth.register") # Cross-blueprint references require the full endpoint blog_url = url_for("blog.index")# Reference to blog blueprint's index * * * ## Templates and Static Files in Blueprints Blueprints can also have their own templates and static files. When a blueprint has its own template folder, Flask first searches in the application's templates, then in the folder specified by the blueprint if not found. ## Example # Create a blueprint with an independent template folder bp = Blueprint("auth", __name__, template_folder="templates") # Blueprint-specific template organization # Path: auth/templates/auth/login.html # When rendering: render_template("auth/login.html") # This organization avoids filename conflicts (login.html might be different in auth and blog) Recommended blueprint directory structure: myflaskapp/β”œβ”€β”€ app.py # Application entry point, registers blueprintsβ”œβ”€β”€ auth.py # Authentication blueprintβ”œβ”€β”€ blog.py # Blog blueprintβ”œβ”€β”€ templates/ # Application-level templates (public base.html, etc.)β”‚ └── base.html β”œβ”€β”€ static/ # Application-level static filesβ”‚ └── style.css β”œβ”€β”€ auth/ # auth blueprint's independent resources (optional)β”‚ └── templates/β”‚ └── auth/β”‚ β”œβ”€β”€ login.html β”‚ └── register.html └── blog/ # blog blueprint's independent resources (optional) └── templates/ └── blog/ β”œβ”€β”€ index.html └── create.html > The simplest approach is not to configure independent template folders for blueprints, but to place templates uniformly under the project root's templates/ directory, using subdirectories to distinguish them: templates/auth/login.html, templates/blog/index.html. * * * ## Factory Patternβ€”create_app As blueprints multiply, creating app = Flask(__name__) directly at the module top level can cause circular import issues. The Factory Pattern is the best practice to solve this problem: ## Example # File path: app.py from flask import Flask def create_app(): """Application factory functionβ€”returns a configured Flask instance""" app = Flask( __name__ ) app.secret_key="dev-secret-key" # Load configuration app.config.from_pyfile("config.py", silent=True) # Import blueprints inside the function to avoid circular references from auth import bp as auth_bp from blog import bp as blog_bp # Register blueprints app.register_blueprint(auth_bp, url_prefix="/auth") app.register_blueprint(blog_bp) return app Advantages of the Factory Pattern: * Eliminates Circular Imports: Blueprints can import app, and app can import blueprints, because imports happen inside the function * Supports Testing: Can create app instances with different configurations for testing * Multi-instance Deployment: The same code can create multiple independent app instances After using the factory pattern, start the application via flask --app "app:create_app()" run: $ flask --app "app:create_app()" run * * * ## Other Functions in Blueprints Blueprints also support decorators like before_request, errorhandler, etc., with usage identical to app: ## Example @bp.before_request def check_login(): """Check login status before all requests in the auth blueprint""" if request.endpoint not in("auth.login","auth.register"): if"username"not in session: return redirect(url_for("auth.login")) @bp.errorhandler(404) def not_found(error): """Auth blueprint-specific 404 error page""" return render_template("auth/404.html"),404 > A blueprint's before_request only affects routes within that blueprint. If you need logic to execute before all requests, you should use app.before_request.
← Flask MiddlewareFlask Form β†’