Serving Static Files and Resources
Blueprints allow you to organize your application into distinct components, each with its own static files and internal resources. This is particularly useful for modular applications where a specific feature (like an admin panel or a user dashboard) needs to bundle its own CSS, JavaScript, or data files.
Configuring a Blueprint Static Folder
To serve static files from a blueprint, specify the static_folder argument when initializing the Blueprint. By default, Flask will serve these files at the blueprint's url_prefix followed by /static.
from flask import Blueprint
# Files in 'my_package/static/' will be served at '/my_feature/static/'
bp = Blueprint(
"my_feature",
__name__,
url_prefix="/my_feature",
static_folder="static"
)
If you want to change the URL path where static files are served, use the static_url_path parameter:
bp = Blueprint(
"assets",
__name__,
static_folder="static",
static_url_path="/assets"
)
Accessing Static URLs in Templates
When a blueprint has a static folder, you can generate URLs for its files using the special static endpoint prefixed with the blueprint's name:
<link rel="stylesheet" href="{{ url_for('my_feature.static', filename='style.css') }}">
Accessing Internal Package Resources
If you need to read a file located within your blueprint's package (such as a SQL schema or a configuration file) programmatically, use the open_resource method. This method ensures the path is correctly resolved relative to the blueprint's root_path.
# In src/flask/blueprints.py, open_resource is defined to read files
# relative to the blueprint's directory.
def init_db(bp):
with bp.open_resource("schema.sql") as f:
schema = f.read().decode("utf-8")
# ... execute schema ...
open_resource supports the following modes:
"r"or"rt": Open for reading in text mode (default encoding is UTF-8)."rb": Open for reading in binary mode.
Serving Static Files Manually
In some cases, you may want to serve a static file from a custom view function rather than the default route. You can use the send_static_file method for this purpose.
@bp.route("/logo")
def serve_logo():
# This serves 'logo.png' from the blueprint's static_folder
return bp.send_static_file("logo.png")
Customizing Cache Headers
You can control how long browsers should cache static files by overriding the get_send_file_max_age method in a subclass of Blueprint. By default, it uses the SEND_FILE_MAX_AGE_DEFAULT configuration from the application.
class MyBlueprint(Blueprint):
def get_send_file_max_age(self, filename):
if filename.endswith(".js"):
return 3600 # Cache JavaScript for 1 hour
return super().get_send_file_max_age(filename)
bp = MyBlueprint("custom", __name__, static_folder="static")
Troubleshooting
Static Files Not Found
If your blueprint's static files are returning 404 errors, check the following:
- URL Prefix Conflicts: If your blueprint does not have a
url_prefix, its static route might conflict with the main application's static route. Always provide aurl_prefixor a uniquestatic_url_pathfor blueprints with static folders. - Missing Folder: Ensure the directory specified in
static_folderactually exists relative to the file where theBlueprintis defined. - Initialization: The
static_foldermust be set during initialization. You cannot serve files viasend_static_fileifstatic_folderwas not provided to the constructor.
Resource Access Errors
open_resource is strictly for reading. Attempting to open a file with write modes (like "w" or "a") will raise a ValueError.
# This will raise ValueError: Resources can only be opened for reading.
with bp.open_resource("data.json", mode="w") as f:
f.write("{}")