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 aString
, finds a single file in your manifest file, according to thekey
get_multi_match
- returns aList
of files in your manifest, according to thepattern
manifest
- this is your full manifest file, after being processed byjson.load()
. It will be a dictionary or list depending on which it is in your manifest file.key
-String
; the argument passed into themanifest
template tag. e.g.: in the template tag{% manifest 'index.js' %}
, the string'index.js'
is sent toget_single_match
askey
(without surrounding quotes)pattern
-String
; the first argument passed into themanifest_match
template tag. e.g.: in the template tag{% manifest_match '*.js' '<script src="{match}"></script>' %}
, the string'*.js'
is sent toget_multi_match
aspattern
(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