skip to navigation
skip to content

django-jsdir 0.3.1

Eases the management of JS files in a django app

© 2014-2015 Thomas Khyn, MIT License


When your project tightly depends on a relatively large amount of JavaScript code, the natural way of dealing with it is to break the JavaScript code down into several sub-scripts. This both improves readability and ease of debugging.

However, there are times when you would be happy to only have one - possibly compressed - file (in production for example) or to not have to link every single standalone js file in your template in development.

django-jsdir aims at solving this issue by providing a way to automatically link the js files in a directory tree with a single template tag and inclusion, exclusion or sorting rules. In this regard it is significantly more flexible than django-pipeline.

django-jsdir has been tested with Django 1.8+ and latest compatible minor Pyhton versions (2.7 and 3.5). It may work - without guarantee - for earlier Django versions.

If you like django-jsdir and are looking for a way to thank me and/or encourage future development, you can send a few mBTC at this Bitcoin address: 1EwENyR8RV6tMc1hsLTkPURtn5wJgaBfG9.


  1. Install using your prefered method, e.g pip install django-jsdir
  2. You will need both 'jsdir' and 'django.contrib.staticfiles' in your INSTALLED_APPS. Make sure that 'jsdir' is placed before 'django.contrib.staticfiles'.
  3. If you are using Jinja2, add 'jsdir.jinja2.ext' to your Jinja2 extensions list

How it works

Directory concatenation

A short real-life example is better than long boring explanations. Suppose you have the following JS files layout:


All the files in big_script are nicely formatted and commented javascript files, perfect for debugging. But you have to include each js file from big_script in your template. And even worse, when deploying your application, you need to concatenate/compress the big_script directory and update your template accordingly. All that entirely manually.

Until now.

With django-jsdir and a few minimal changes, you will not have to worry about that anymore. The only thing to do is to get rid of all the <script> tags refering to big_script/*.js files in your template, and replace them by:

{% jsdir 'big_script' %}

django-jsdir will then take care of:

  1. linking all the scripts nested under big_script directory tree when in development mode with files served from the application’s static directory. This will change nothing from the developer’s point of view, except he won’t need to update the script list anymore
  2. concatenating (and possibly compressing, with the help of django-compressor) all the nested subscripts in one file named big_script.dir.js either on the first request or when you’ll run collectstatic, depending if the file already exists or not
  3. linking the generated big_script.dir.js when in production mode

In other words, you do not have to change your production template (or scratch your head to find a way to do it programmatically with conditional extends or includes) AND you do not have to manually concatenate and/or compress your JS files anymore.


As in JS, the order in which the files are loaded matters, it is worth noting that the default concatenation order will be alphabetic. Use numbers with a fixed number of digits to name your JS files, for example.


If a directory bar.js is nested into a foo.js directory, no bar.js file will be generated. All the files in the bar.js directory will be concatenated in the foo.js file.

include and exclude keywords

django-jsdir has ways to refine what files in the directory you want to explicitely include or exclude.

Use them like that:

{% jsdir 'libs' expand=True include='jquery/jquery.js; jquery-ui/ui/*.js' exclude='effect-*.js' %}

This will load jquery.js and all the jquery-ui files except the effect files.

The patterns:

  • are Unix-like. See fnmatch.
  • should either be provided as a semicolon-separated string (spaces at the beginning and at the end of each pattern are stripped) or, for jinja2 templates, as a list or tuple
  • ‘file.js’ will matche both ‘file.js’ and ‘file.min.js’


The include keyword as priority over the exclude one. When the include keyword is provided, all files not matching patterns in the include keyword will be excluded.

name keyword

The name keyword is only used when you are loading a directory multiple times, to avoid name collision on concatenation.

For example:

{% jsdir 'libs' exclude='jquery-ui/**' %}
{% jsdir 'libs' name='jquery-ui' include='jquery-ui/**' %}

will create, in production mode, 2 files libs.dir.js and libs.jquery-ui.dir.js. libs.dir.js will contain all libraries except jquery-ui, while libs.jquery-ui.dir.js will contain only jquery-ui.

This is particularly useful when you need to generate 2 files containing different libraries that are located in one directory (when using bower to manage your javascript libraries, for example).

Inclusion of all files in a directory

Sometimes, you will prefer to import the javascript files from a directory without seeing them concatenated at all. It is the case if you have a ‘lib’ folder containing javascript librairies. In that situation, you may use the tag argument expand:

{% jsdir 'lib/' expand=True %}

In production (i.e. with DEBUG = False), jsdir will look for minified versions of the scripts (files named *.min.js) and return corresponding HTML tags. If you don’t want this behavior, you can use the tag argument minified and set it to False:

{% jsdir 'lib' expand=True minified=False %}

Remember that the order in which the HTML tags will appear in the document, and therefore the order in which the JS files will be loaded is still alphabetic. You can however ask django-jsdir to load certain files first or last.

first and last keywords

In case you want to load some files first in the included expanded directory, django-jsdir provides the first and last keywords.

Use them like that:

{% jsdir 'lib' expand=True first='1st_pattern; 2nd_pattern' last='verylast_parttern; 2ndtolast_pattern' %}

Any file which name matches the glob pattern ‘1st_pattern’ will be loaded before any file which name matches ‘2nd_pattern’, which will be loaded before any other file, which will be loaded before any file which name matches ‘2ndtolast_pattern’, which will be loaded before any file which name matches ‘verylast_pattern’.


first and last keywords are only available when expand=True is used


If you are using the include keyword described above, there is no need to relist them in the first keyword argument. Indeed, the include keyword already has a sorting functionality.


If you wish to have big_script.dir.js compressed, django-jsdir integrates without a fuss with django-compressor. In production, the script gets compressed like any other js file. Simply use:

{% compress %}
    {% jsdir 'big_script' %}
{% endcompress %}


The default url to access the javascript files directory, relative to the static files root. Defaults to 'js'. This prefix can be bypassed using ‘absolute’ paths (for example {% jsdir '/path/to/dir' %}).
File Type Py Version Uploaded on Size (md5) Source 2015-10-22 21KB
  • Downloads (All Versions):
  • 20 downloads in the last day
  • 134 downloads in the last week
  • 745 downloads in the last month