Serving Static Files and Resources
When you create a Flask application, it automatically sets up a route to serve static files like CSS, JavaScript, and images from a folder named static located next to your application module. The Scaffold class provides the base logic for resource management, which is inherited by both the Flask application and Blueprint objects.
Configuring the Static Folder
By default, Flask looks for a folder named static relative to the application's root_path. You can customize the folder name and the URL path used to access it during initialization.
from flask import Flask
from pathlib import Path
# Customizing the static folder and URL path
app = Flask(
__name__,
static_folder="assets", # Files located in 'assets/' directory
static_url_path="/public" # Accessed via 'http://domain/public/...'
)
# You can also use pathlib.Path objects
app = Flask(__name__, static_folder=Path("static_files"))
If you use host_matching=True, you must also provide a static_host to the constructor, or Flask will raise an AssertionError during initialization.
Generating Static URLs
To generate a URL for a static file, use the url_for helper with the static endpoint.
from flask import url_for
@app.route("/")
def index():
# Returns '/static/style.css' (or your custom static_url_path)
return url_for("static", filename="style.css")
Serving Static Files Manually
While Flask automatically registers a route for static files, you can manually serve files from the configured static_folder using the send_static_file method. This is useful if you need to perform custom logic before serving the file.
@app.route("/get-manifest")
def manifest():
# Serves 'manifest.json' from the app's static_folder
return app.send_static_file("manifest.json")
The send_static_file method uses send_from_directory internally and respects the SEND_FILE_MAX_AGE_DEFAULT configuration for caching.
Reading Application Resources
If you need to read internal files that are part of your application package (like a SQL schema or a configuration file), use open_resource. This method resolves paths relative to the application's root_path.
# example from flaskr tutorial
with app.open_resource("schema.sql") as f:
db.executescript(f.read().decode("utf8"))
open_resource only supports reading. Valid modes are "r", "rt", and "rb". If you attempt to open a file for writing, it will raise a ValueError.
Managing Instance Resources
For files that need to be written at runtime or should not be part of the version-controlled source code, use the instance folder. The open_instance_resource method allows both reading and writing relative to the instance_path.
# Writing to a file in the instance folder
with app.open_instance_resource("data.log", mode="w") as f:
f.write("Log entry")
# Reading from the instance folder
with app.open_instance_resource("config.json", mode="rb") as f:
config_data = f.read()
Static Files in Blueprints
Blueprints can also serve their own static files. This allows you to package a component with its own assets.
from flask import Blueprint
# Blueprint with its own static folder
admin_bp = Blueprint(
"admin",
__name__,
static_folder="admin_static",
static_url_path="/admin/static"
)
# Accessing blueprint static files in templates:
# {{ url_for('admin.static', filename='admin_style.css') }}
Note that the static route for a blueprint is only registered if static_folder is explicitly provided during the Blueprint creation.
Cache Configuration
You can control how long browsers should cache static files by setting the SEND_FILE_MAX_AGE_DEFAULT configuration option.
from datetime import timedelta
# Set cache timeout to 1 hour
app.config["SEND_FILE_MAX_AGE_DEFAULT"] = timedelta(hours=1)
# Or use an integer (seconds)
app.config["SEND_FILE_MAX_AGE_DEFAULT"] = 3600
If this is set to None (the default), the browser will use conditional requests to check if the file has changed instead of relying on a timed cache.
Troubleshooting
- Missing Static Route: The
staticroute is only added ifhas_static_folderis true. ForFlaskapps, this defaults to'static', but forBlueprints, it defaults toNone. - Trailing Slashes: The
static_url_pathandstatic_foldersetters in theScaffoldclass automatically strip trailing slashes to ensure consistent path joining. - Root Path Detection: Flask uses the
import_name(usually__name__) to find theroot_path. If your resources aren't being found, ensure you are passing the correct module or package name to theFlaskconstructor. - Read-Only Resources:
open_resourceis strictly for reading. If you need to write files, useopen_instance_resourceor standard Pythonopen()with absolute paths.