[PYTHON] Solve the problem that CSS is not reflected during web application development in Flask

I'm developing a web app in Flask. At that time, I thought about how to deal with the problem that CSS is cached in the Web browser.

When linking CSS in HTML, you may have manually added the modification date and version, such as style.css? V = 12. However, since I am using Python, I would like you to solve this automatically.

Model answer

After searching, the model answer is that you should rewrite the url_for as follows.

app.py


@app.context_processor
def override_url_for():
    return dict(url_for=dated_url_for)

def dated_url_for(endpoint, **values):
    if endpoint == 'static':
        filename = values.get('filename', None)
        if filename:
            file_path = os.path.join(app.root_path,
                                 endpoint, filename)
            values['q'] = int(os.stat(file_path).st_mtime)
    return url_for(endpoint, **values)

And in the template, link as follows

hoge.html


<link rel= "stylesheet" type= "text/css" 
 href= "{{ url_for('static',filename='style.css') }}">

A technique that overwrites the url_for in the context processor. It is a technique to add the file modification date when static is specified for the endpoint.

By the way, the following is the English page of the original story. It was introduced in other blogs in Japan as a reference. (Reference) https://stackoverflow.com/questions/21714653/flask-css-not-updating

Dissatisfied with this answer, or dissatisfied with Flask's url_for

However, as I always think, using url_for is long when you just write a static link. It's a hassle. In Flask, static files are placed under / static by default, so the path to place CSS should already be decided. In other words, using url_for when you just embed a static file feels quite annoying.

So, I cut corners and thought about the following method.

Omission answer-an example of half failure

The first way is to use a filter.

app.py


@app.template_filter('staticfile')
def staticfile_filter(fname):
    path = os.path.join(app.root_path, 'static', fname)
    mtime =  str(int(os.stat(path).st_mtime))
    return '/static/' + fname + '?v=' + str(mtime)

Write the template as follows.

hoge.html


<link rel="stylesheet" type="text/css"
 href="{{ 'style.css' | staticfile }}">

It was much more elegant than the model answer.

However, the problem with this method is that the template engine caches the HTML, so the cache is not updated instantly. Still, it looks like style.css? V = xxx.

Omission answer # 2 Add context_processor

After all, I thought about chewing the model answer and using context_processor.

app.py


@app.context_processor
def add_staticfile():
    def staticfile_cp(fname):
        path = os.path.join(app.root_path, 'static', fname)
        mtime =  str(int(os.stat(path).st_mtime))
        return '/static/' + fname + '?v=' + str(mtime)
    return dict(staticfile=staticfile_cp)

And the template looks like this

hoge.html


<link rel="stylesheet" type="text/css"
 href="{{ staticfile('style.css') }}">

In this case, it is not cached, the value is reflected instantly, and it does not look so bad, is it okay?

Impressions

The combination of Flask + jinja2 is easy to use and easy to expand, so I like it. The findings obtained are as follows.

--If you use a filter, the contents will not be rewritten unless you change the template. --Using the context processor, the value is always up-to-date because it is executed before the embedding process in the template.

Recommended Posts

Solve the problem that CSS is not reflected during web application development in Flask
Test.py is not reflected on the web server in Python3.
[VLC] How to deal with the problem that it is not in the foreground during playback
Web application development with Flask
Web application development memo in python
The road to web application development is a long way off
Solves the problem that static files (CSS, JS, img) are not read when DEBUG = False in Django.
Try using the web application framework Flask
Solve the maximum subarray problem in Python
Web application development in Go language_Hands-on day 1
[Jinja2] Solution to the problem that variables added in the for statement are not inherited
[Pyhton] I want to solve the problem that tkinter does not work on MacOS11
Solved the problem that the image was not displayed in ROMol when loaded with PandasTools.LoadSDF.
A solution to the problem that files containing [and] are not listed in glob.glob ()
How to solve the problem that the login screen is not displayed forever on Ubuntu 19.04 because it stops at the logo at startup
Until the web application is released on Sakura VPS
When the selected object in bpy.context.selected_objects is not returned
Linux is something like that in the first place
Find the part that is 575 from Wikipedia in Python
Challenge problem 5 that software engineers should solve in 1 hour
The story that yapf did not work in vscode
About the matter that nosetests does not pass when __init__.py is created in the project directory
The image is displayed in the local development environment, but the image is not displayed on the remote server of VPS