Static file management
#Static file management: elegantly load CSS, JavaScript and local images
📂 Stage: Stage 1 - Breaking the ice and setting sail (Basics) 🔗 Related chapters: Jinja2 模板引擎(下) · environment-setup
In the previous articles, we learned to use Jinja2 templates to render dynamic content, but text and variables alone are too simple! To make the page look beautiful and interactive, you need styles, scripts, pictures, and user-uploaded files — these are all static files. Today I will explain the routine of Flask static file management in one go, from getting started to avoiding pitfalls👇
1. Static file directory: Flask gives you the green light by default
Flask has built-in static file service, no additional routing is needed, just put the file into the agreedstatic/Just a folder** will do.
1.1 Standard directory structure
⚠️ Note: All files that need to be accessed directly through the browser (such as CSS, JS, images, public uploaded files) must be placed
static/down, otherwise it will be 404 when accessed.
1.2 Register additional static folders (optional scenario)
If you have a "media library" that comes with the project and don't want to plug it intostatic/, such as located in the project root directorymedia/A folder can expose its access path in the following two ways.
Method 1: Flask native routing (suitable for temporary, fewer files)
Method 2: Werkzeug middleware (suitable for stability, high traffic, and large files)
💡 Tips: In most scenarios, use the default
static/The directory is enough. Custom static folders are mainly used for some special needs, such as sharing folders with existing systems.
2. Elegantly reference static files in templates
**Never write hard/static/css/style.css! ** useurl_for('static', filename=...)The generated URL is more flexible - even if the routing prefix of the static file is changed later, or the project is deployed to a subdirectory, there is no need to change the link everywhere.
2.1 Basic reference gestures
2.2 Must do in production environment: add version number to static files
Browsers cache static files by default. If you update CSS or JS, users may still see the old version. The solution is to append a version parameter to the resource address. There are two common methods.
🟢 Manually add version number (temporary use for small projects)
Disadvantages: Every time you modify a file, you have to manually change the version number, which is easy to forget.
🟢 Automatically generate hash values (recommended, once and for all)
Use MD5 to generate an 8-bit hash based on the file content. The hash will only change when the file content changes, and does not affect the cache of unchanged files.
Then register this function as a global template function, so that all templates can use it directly.
Use it like this in the template:
✨ Just modify it in the future
style.cssAnd redeploy, the user's browser will automatically load the latest version, no additional operations are required.
3. CSS organization and coverage skills
3.1 Design a common master style sheet
It is recommended that variables, reset styles, and layout containers that are common to the entire site should be written instatic/css/style.cssinside. The exclusive style of the subpage uses Jinja2'sblockInsert to avoid cluttering all your CSS together.
3.2 Quick integration of Bootstrap
Don't want to write the layout from scratch? Bootstrap is a mature choice, and the two introduction methods can be used as needed.
Method 1: CDN (preferred for development stage or small projects, no need to download files)
Method 2: Local file (no external network environment or production environment optimization)
Go to Bootstrap official website to download the compiled compressed package, andbootstrap.min.cssput instatic/css/,bootstrap.bundle.min.jsput instatic/js/, then useurl_fororstatic_hashJust quote.
3.3 Subtemplate append/override styles
existbase.htmlReserve one inextra_headBlocks, sub-templates can add their own here<style>or<link>。
4. File upload: public files are handled like this
This section only covers uploaded files that require public access (such as user avatars and public images). Private attachments should existstatic/In addition, use a special view to authenticate before outputting, which will be discussed in the advanced chapter later.
4.1 Security configuration and auxiliary functions
existapp/__init__.py(or a separate configuration module).
Then write a general extension checking function (usually defined in the blueprint file where the view is located):
⚠️
allowed_fileUsed internallycurrent_app.config, so it must be called within the request context (that is, used temporarily in the view function, or as an auxiliary function of the view function).
4.2 Write upload route (take avatar as an example)
4.3 Upload form with preview
The form must be addedenctype="multipart/form-data", otherwise the file cannot be submitted.
5. Let the browser find the favicon obediently
By default, the browser will request the root directory of the website.favicon.ico, but the safest way is to put the icon instatic/down, then onbase.htmlof<head>explicitly specified.
✅ Even if the browser has smart search for multiple tabs, it is recommended to add this line to reduce unnecessary requests and error logs.
6. Summary & Best Practices
A picture is worth a thousand words
🛠️ Recommended good habits to develop
- Categorized storage, no confusion - Don’t throw CSS, JS, images, and uploaded files directly in
static/Root directory, classified by folders. - The development version relies on Flask, and the online version relies on Nginx/Apache - Flask's own static file service efficiency is low, and the production environment must be handed over to the reverse proxy.
- Keep private files away
static/- User private attachments, ID photos, etc. must not be placed in a directory that can be directly accessed through URL, and must be output using a view with permission control. - Production environment compression and merging - You can use tools (such as Flask-Assets, Webpack) to package and compress multiple CSS/JS, greatly reducing the number of requests.
🔗 Extended reading

