Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

django static files versioning

I'm working on some universal solution for problem with static files and updates in it.

Example: let's say there was site with /static/styles.css file - and site was used for a long time - so a lot of visitors cached this file in browser

Now we doing changes in this css file, and update on server, but some users still have old version (despite modification date returned by server)

The obvious solution is to add some version to file /static/styles.css?v=1.1 but in this case developer must track changes in this file and manually increase version

A second solution is to count the md5 hash of the file and add it to the url /static/styels.css/?v={mdp5hashvalue} which looks much better, but md5 should be calculated automatically somehow.

they possible way I see it - create some template tag like this

{% static_file  "style.css" %} 

which will render

<link src="/static/style.css?v=md5hash"> 

BUT, I do not want this tag to calculate md5 on every page load, and I do not want to store hash in django-cache, because then we will have to clear after updating file...

any thoughts ?

like image 336
Pydev UA Avatar asked Feb 03 '12 14:02

Pydev UA


People also ask

Where are Django static files stored?

Using the collectstatic command, Django looks for all static files in your apps and collects them wherever you told it to, i.e. the STATIC_ROOT . In our case, we are telling Django that when we run python manage.py collectstatic , gather all static files into a folder called staticfiles in our project root directory.

What is Collectstatic Django?

collectstatic. django-admin collectstatic. Collects the static files into STATIC_ROOT . Duplicate file names are by default resolved in a similar way to how template resolution works: the file that is first found in one of the specified locations will be used.


2 Answers

Django 1.4 now includes CachedStaticFilesStorage which does exactly what you need (well... almost).

Since Django 2.2 ManifestStaticFilesStorage should be used instead of CachedStaticFilesStorage.

You use it with the manage.py collectstatic task. All static files are collected from your applications, as usual, but this storage manager also creates a copy of each file with the MD5 hash appended to the name. So for example, say you have a css/styles.css file, it will also create something like css/styles.55e7cbb9ba48.css.

Of course, as you mentioned, the problem is that you don't want your views and templates calculating the MD5 hash all the time to find out the appropriate URLs to generate. The solution is caching. Ok, you asked for a solution without caching, I'm sorry, that's why I said almost. But there's no reason to reject caching, really. CachedStaticFilesStorage uses a specific cache named staticfiles. By default, it will use your existing cache system, and voilà! But if you don't want it to use your regular cache, perhaps because it's a distributed memcache and you want to avoid the overhead of network queries just to get static file names, then you can setup a specific RAM cache just for staticfiles. It's easier than it sounds: check out this excellent blog post. Here's what it would look like:

CACHES = {   'default': {     'BACKEND': 'django.core.cache.backends.memcached.PyLibMCCache',     'LOCATION': '127.0.0.1:11211',   },   'staticfiles': {     'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',     'LOCATION': 'staticfiles-filehashes'   } } 
like image 186
MiniQuark Avatar answered Sep 24 '22 13:09

MiniQuark


I would suggest using something like django-compressor. In addition to automatically handling this type of stuff for you, it will also automatically combine and minify your files for fast page load.

Even if you don't end up using it in entirety, you can inspect their code for guidance in setting up something similar. It's been better vetted than anything you'll ever get from a simple StackOverflow answer.

like image 22
Chris Pratt Avatar answered Sep 22 '22 13:09

Chris Pratt