Automatic asset versioning in Django

By: summonagus ● at Sept. 6, 2017, 7:36 p.m. ● and modified at Sept. 6, 2017, 7:37 p.m.
Posted under: #Tricks, #Django, #Project, #Solution, #Performance ● Your ip address: ● views: 20 times.

AD Space Available, Book Now!

Following on from Ed's "Automatic versioning of CSS, JavaScript and Images" here is a method to version filenames based on modification times to be used in Django as a template tag.

This is really handy technique for when you set expires headers to a long way into the future. With headers set in this way files need to have their filenames versioned to force the client to download the latest version of a file. The purpose being that with far futures expires the browser will agressively cache the asset thus minimising the amount of requests for assets.

This template tag for Django uses the same method as Ed's to provide a version string that's appended to the filename. The awesome part of this is once configured you can just happily change the file as you need to and the caching is taken care of.

{% load utils %}
<link rel="stylesheet" type="text/css" href="{% version '/static/css/style.css' %}">

The code for this is placed in a in "project/app/templatetags"

from django import template  
register = template.Library()
import os, re        

version_cache = {}

rx = re.compile(r"^(.*)\.(.*?)$")
def version(path_string):                                                                 
        if path_string in version_cache:
            mtime = version_cache[path_string]
            mtime = os.path.getmtime('%s%s' % (STATIC_PATH, path_string,))
            version_cache[path_string] = mtime

        return rx.sub(r"\1.%d.\2" % mtime, path_string)
        return path_string 


As Brad has pointed out in the comments below the original query string method used will not be cached by UAs following the http spec. The output will now look like the following:


In addition a mod_rewrite rule is required to map the versioned file to the original.

RewriteRule ^/static/(.*?)\.[0-9]+\.(css|js|jpe?g|gif|png) /static/$1\.$2 [L]

Original Source:



Python Developer, Linux Enthusiast, and Senior writer at
blog comments powered by Disqus