Basic Usage

Django Manifest Loader comes with two template tags that house all logic. The manifest tag takes a single string input, such as 'main.js', looks it up against the webpack manifest, and then outputs the URL to that compiled file. It works just like Django’s built it static tag, except it’s finding the filename according to your manifest file.

The manifest_match tag takes two arguments, a string to pattern match filenames against and a string to embed matched file urls into. See the manifest_match section for more information.

Manifest tag

{% load manifest %}

<script src="{% manifest 'main.js' %}"></script>

turns into

<script src="/static/main.8f7705adfa281590b8dd.js"></script>

Where the argument to the tag will be the original filename of a file processed by webpack. If in doubt, check your manifest.json file generated by webpack to see what files are available.

This is worthwhile because of the content hash after the original filename, which will invalidate the browser cache every time the file is updated, which will ensure that your users always have the latest assets.

Manifest match tag

{% load manifest %}

{% manifest_match '*.js' '<script src="{match}"></script>' %}

turns into

<script src="/static/vendors~main.3ad032adfa281590f2a21.js"></script>
<script src="/static/main.8f7705adfa281590b8dd.js"></script>

This tag takes two arguments, a pattern to match against, according to the python fnmatch package rules, and a string to input the file URLs into. The second argument must contain the string {match}, as it is replaced with the URLs.

Advanced Usage

Use as Jinja template filter

Use with django-jinja is very similar to usage with Django templating. In the jinja configuration you need to point to the filters like:

# settings.py

TEMPLATES = [
    {
        "BACKEND": "django_jinja.backend.Jinja2",
        "OPTIONS": {
            "filters": {
                "manifest": "manifest_loader.utils.manifest",
                "manifest_match": "manifest_loader.utils.manifest_match",
            }
        }
    },
]

The manifest filter takes a single argument:

<script src="{{ 'main.js'|manifest }}"></script>

And the manifest match filter:

{{ '*.js'|manifest_match('<script src="{match}"></script>') }}

All other instructions in this documentation should be followed as normal.

Use outside of templates

If you need the functions of the manifest and manifest_match template tags, you can import their core logic into your python project and use them exactly as you would in your templates.

>>> # register django settings if using in python console
>>> from manifest_loader.utils import manifest, manifest_match
>>>
>>> manifest('main.js')
'/static/main.e12dfe2f9b185dea03a4.js'
>>>
>>> manifest_match('*.js', '{match}')
'/static/main.e12dfe2f9b185dea03a4.js\n/static/chunk1.hash.js\n/static/chunk2.hash.js\n/static/chunk3.hash.js'

Custom Loaders

Custom loaders allow you to implement your own means of extracting data from your manifest file. If your manifest file is not the default structure of webpack manifest plugin, this is how you can tell django-manifest-loader how to read it.

First import the loader parent abstract class, and subclass it in your new loader class.

from manifest_loader.loaders import LoaderABC

class MyCustomLoader(LoaderABC):

Your new loader must have two static methods that each take two required arguments: get_single_match(manifest, key) and get_multi_match(manifest, pattern).

from manifest_loader.loaders import LoaderABC

class MyCustomLoader(LoaderABC):
    @staticmethod
    def get_single_match(manifest, key):
        pass

    @staticmethod
    def get_multi_match(manifest, pattern):
        pass
  • get_single_match - returns a String, finds a single file in your manifest file, according to the key

  • get_multi_match - returns a List of files in your manifest, according to the pattern

  • manifest - this is your full manifest file, after being processed by json.load(). It will be a dictionary or list depending on which it is in your manifest file.

  • key - String; the argument passed into the manifest template tag. e.g.: in the template tag {% manifest 'index.js' %}, the string 'index.js' is sent to get_single_match as key (without surrounding quotes)

  • pattern - String; the first argument passed into the manifest_match template tag. e.g.: in the template tag {% manifest_match '*.js' '<script src="{match}"></script>' %}, the string '*.js' is sent to get_multi_match as pattern (without surrounding quotes)

Below is the code for the default loader, which is a good starting point:

import fnmatch
from manifest_loader.loaders import LoaderABC

class DefaultLoader(LoaderABC):
    @staticmethod
    def get_single_match(manifest, key):
        return manifest.get(key, key)

    @staticmethod
    def get_multi_match(manifest, pattern):
        matched_files = [file for file in manifest.keys() if
                         fnmatch.fnmatch(file, pattern)]
        return [manifest.get(file) for file in matched_files]

In the above example, get_single_match retrieves the value on the manifest dictionary that matches the key key. If the key does not exist on the dictionary, it instead returns the key.

get_multi_match uses the recommended fnmatch python standard library to do pattern matching. You could also use regex in it’s place. Here, it iterates through all the keys in the manifest file, and builds a list of the keys that match the given pattern. It then returns a list of the values associated with those matched keys.

Activating the custom loader

To put the custom loader into use it needs to be registered in your settings.py.

# settings.py
from my_app.utils import MyCustomLoader

MANIFEST_LOADER = {
    ...
    'loader': MyCustomLoader
}

URLs in Manifest File

If your manifest file points to full URLs, instead of file names, the full URL will be output instead of pointing to the static file directory in Django.

Example:

{
  "main.js": "http://localhost:8080/main.js"
}
{% load manifest %}

<script src="{% manifest 'main.js' %}"></script>

Will output as:

<script src="http://localhost:8080/main.js"></script>

Tests and Code Coverage

Run unit tests and verify 100% code coverage with:

git clone https://github.com/shonin/django-manifest-loader.git
cd django-manifest-loader
pip install -e .

# run tests
python runtests.py

# check code coverage
pip install coverage
coverage run --source=manifest_loader/ runtests.py
coverage report