Static files¶
As their name suggests, static files are the files that don’t change. In your average app, this includes CSS files, JavaScript files and images. They can also include audio files and other things of that nature.
Organizing your static files¶
We’ll create a directory for our static files called static inside our application package.
1 2 3 4 5 6 7 | myapp/
__init__.py
static/
templates/
views/
models.py
run.py
|
How you organize the files in static/ is a matter of personal preference. Personally, I get a little irked by having third-party libraries (e.g. jQuery, Bootstrap, etc.) mixed in with my own JavaScript and CSS files. To avoid this, I recommend separating third-party libraries out into a lib/ folder within the appropriate directory. Some projects use vendor/ instead of lib/.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | static/
css/
lib/
bootstrap.css
style.css
home.css
admin.css
js/
lib/
jquery.js
home.js
admin.js
img/
logo.svg
favicon.ico
|
Serving a favicon¶
The files in our static directory will be served from
example.com/static/. By default, web browsers and other software
expects our favicon to be at example.com/favicon.ico. To fix this
discrepency, we can add the following in the <head>
section of our
site template.
1 2 | <link rel="shortcut icon"
href="{{ url_for('static', filename='img/favicon.ico') }}">
|
Manage static assets with Flask-Assets¶
Flask-Assets is an extension for managing your static files. There are two really useful tools that Flask-Assets provides. First, it lets you define bundles of assets in your Python code that can be inserted together in your template. Second, it lets you pre-process those files. This means that you can combine and minify your CSS and JavaScript files so that the user only has to load two minified files (CSS and JavaScript) without forcing you to develop a complex asset pipeline. You can even compile your files from Sass, LESS, CoffeeScript and a bunch of other sources.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | static/
css/
lib/
reset.css
common.css
home.css
admin.css
js/
lib/
jquery-1.10.2.js
Chart.js
home.js
admin.js
img/
logo.svg
favicon.ico
|
Defining bundles¶
Our app has two sections: the public site and the admin panel, referred
to as “home” and “admin” respectively in our app. We’ll define four
bundles to cover this: a JavaScript and CSS bundle for each section.
We’ll put these in an assets module inside our util
package.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | # myapp/util/assets.py
from flask_assets import Bundle, Environment
from .. import app
bundles = {
'home_js': Bundle(
'js/lib/jquery-1.10.2.js',
'js/home.js',
output='gen/home.js'),
'home_css': Bundle(
'css/lib/reset.css',
'css/common.css',
'css/home.css',
output='gen/home.css'),
'admin_js': Bundle(
'js/lib/jquery-1.10.2.js',
'js/lib/Chart.js',
'js/admin.js',
output='gen/admin.js'),
'admin_css': Bundle(
'css/lib/reset.css',
'css/common.css',
'css/admin.css',
output='gen/admin.css')
}
assets = Environment(app)
assets.register(bundles)
|
Flask-Assets combines your files in the order in which they are listed here. If admin.js requires jquery-1.10.2.js, make sure jquery is listed first.
We’re defining the bundles in a dictionary to make it easy to register them. webassets, the package behind Flask-Assets lets us register bundles in a number of ways, including passing a dictionary like the one we made in this snippet. 1
Since we’re registering our bundles in util.assets
, all we have to
do is import that module in __init__.py after our app has been
initialized.
1 2 3 4 5 | # myapp/__init__.py
# [...] Initialize the app
from .util import assets
|
Using our bundles¶
To use our admin bundles, we’ll insert them into the parent template for the admin section: admin/layout.html.
1 2 3 4 5 6 7 8 9 | templates/
home/
layout.html
index.html
about.html
admin/
layout.html
dash.html
stats.html
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | {# myapp/templates/admin/layout.html #}
<!DOCTYPE html>
<html lang="en">
<head>
{% assets "admin_js" %}
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
{% endassets %}
{% assets "admin_css" %}
<link rel="stylesheet" href="{{ ASSET_URL }}" />
{% endassets %}
</head>
<body>
{% block body %}
{% endblock %}
</body>
</html>
|
We can do the same thing for the home bundles in templates/home/layout.html.
Using filters¶
We can use filters to pre-process our static files. This is especially handy for minifying our JavaScript and CSS bundles.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | # myapp/util/assets.py
# [...]
bundles = {
'home_js': Bundle(
'lib/jquery-1.10.2.js',
'js/home.js',
output='gen/home.js',
filters='jsmin'),
'home_css': Bundle(
'lib/reset.css',
'css/common.css',
'css/home.css',
output='gen/home.css',
filters='cssmin'),
'admin_js': Bundle(
'lib/jquery-1.10.2.js',
'lib/Chart.js',
'js/admin.js',
output='gen/admin.js',
filters='jsmin'),
'admin_css': Bundle(
'lib/reset.css',
'css/common.css',
'css/admin.css',
output='gen/admin.css',
filters='cssmin')
}
# [...]
|
Note
To use the jsmin
and cssmin
filters, you’ll need to install the
jsmin
and cssmin
packages (e.g. with
pip install jsmin cssmin
). Make sure to add them to
requirements.txt too.
Flask-Assets will merge and compress our files the first time the template is rendered, and it’ll automatically update the compressed file when one of the source files changes.
Note
If you set ASSETS_DEBUG = True in your config, Flask-Assets will output each source file individually instead of merging them.
Note
Take a look at some of the other filters that we can use with Flask-Assets.
Summary¶
Static files go in the static/ directory.
Separate third-party libraries from your own static files.
Specify the location of your favicon in your templates.
Use Flask-Assets to insert static files in your templates.
Flask-Assets can compile, combine and compress your static files.
- 1
We can see how bundle registration works in the source.