When I started with Django, the version at the time was 1.5. Back then, we prepended STATIC_URL
to our static assets to reference them in our templates. With recent release, best practice is to you use the static
[1]. I often find myself wanting to append a version number to my static files, at least my CSS and JS files to ensure that browser see my new versions when I push an update. In this post, I make use of the `static` tag and its URL building to easily append a version number.
The Code
The static
tag uses the active storage engine to generate the URL for the static file, by default this is the StaticFilesStorage
engine. So we’re going to want to subclass this engine and override the, url()
method to generate our versioned URL.
# django imports from django.conf import settings from django.contrib.staticfiles.storage import StaticFilesStorage from django.utils.encoding import filepath_to_uri from django.utils.six.moves.urllib.parse import parse_qs from django.utils.six.moves.urllib.parse import urlencode VERSION_NAME = u'v' # classes class VersionedStaticFilesStorage(StaticFilesStorage): def url(self, name): """ Generates URL for static file. Requires STATICFILES_VERSION setting. """ # if there is a query string already, isolate it try: idx = name.index(u'?') qs = name[idx+1:] name = name[:idx] except ValueError: idx = -1 qs = None # build a dictionary query = parse_qs(qs) if qs else {} # add in our version number query[VERSION_NAME] = settings.STATICFILES_VERSION # get url url = super(VersionedStaticFilesStorage, self).url(name) # rebuild query string qs = urlencode(query.items(), doseq=True) # return combined url return url + u'?' + qs pass
Add this code to a module, for example, storage.py
in your app, and then reference it in the STATICFILES_STORAGE
setting.
STATICFILES_STORAGE = 'myapp.storage.VersionedStaticFilesStorage'
Be sure to create your version value in settings.py
:
STATICFILES_VERSION = '2.0'
And now you should have static URLs like this:
<script type="text/javascript" src="/static/js/bootstrap.min.js?v=2.0"></script>
Good luck, and happy coding.