-Kipling
Here is the situation: you want to use the Moustache templating engine in Django and are having trouble getting it to work. The online documentation on the topic seems very thorough but you are having configuration issues which are causing problems and nothing works. The primary source of this issue is that the documentation assumes a lot of knowledge, the lack of which which can cause those inexperienced with Django and JavaScript/Moustache considerable trouble. This note is an attempt to fill in the blanks in the documentation with novice friendly advice and is basically the information that I would have liked to have had available when I was trying to get the django-jstemplate
app working.
Below are some error messages you may be seeing - all of these have to be resolved or the templating engine will not work. Note: On this page, and in the messages below, the text "ABC" is the name of the Django app the engine is working on - consider it to be a placeholder for your app name.
So, lets take them one issue at a time and find out what is going on.
django-jstemplate
Be aware that installing django-jstemplate
does not give you the mustache.js
code. You still have to include that script in your Django page template. All the django-jstemplate
app is really doing is providing you with the functionality that will allow you to access the mustache templates in a nice Django'ish way.
To get the mustache.js
code, the file you want is mustache.min.js
and there are several ways to introduce this into your web page.
mustache.min.js
and serve it as a static file in the usual Django way.
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
django-mustachejs
is Now Named django-jstemplate
Let's clarify what this page is discussing (and what you may be working with). The django-mustachejs
app
has been renamed to django-jstemplate
. Other than the usual minor upgrade sort of stuff they both serve exactly the same purpose and do exactly the same thing.
Be aware of which app you are working with and especially be aware that this name change also introduces a number of important configuration changes to your settings.py
file (and others). A lot of the documentation you may read on the Internet will be discussing the configuration for django-mustachejs
. The migration is simple - but when debugging it is important to be aware of what app you are actually using.
Install the django-jstemplate
app by running something like the following:
pip install django-jstemplateIf you have installed
django-mustachejs
you may wish to run a command like the following to remove it:
pip uninstall django-mustachejsCheck your
settings.py
file and your Django templates. Here is a summary of the name changes
settings.py
INSTALLED_APPS
section, "mustachejs"
becomes "jstemplate"
MUSTACHEJS_DIRS
settings becomes JSTEMPLATE_DIRS
MUSTACHEJS_EXTS
settings becomes JSTEMPLATE_EXTS
{% load mustachejs %}
becomes {% load jstemplate %}
django-mustachejs
then a lot of the information on this page will still be useful but you are going to
have to translate some of the settings.py
code.
The INSTALLED_APPS
section of your settings.py
should have a line in it that looks like:
'jstemplate',
settings.py
File.
The JSTEMPLATE_DIRS
section of your settings.py
should point at the directories in which your templates are located:
JSTEMPLATE_DIRS = [ os.path.join(BASE_DIR, 'ABC/jstemplates/ABC'), ]Of course, the path can be whatever you wish and you can have multiple entries (one per line) for different apps. It works similar to the
STATICFILES_DIRS
setting with one important exception. You can NOT us the BASE_DIR
construct in JSTEMPLATE_DIRS
in the way you do in the STATICFILES_DIRS
section. For example, the code below will generate an error of TypeError at /ABC/ object of type 'WindowsPath' has no len()
. The django-jstemplate
code that parses the JSTEMPLATE_DIRS
section simply is not that clever.
JSTEMPLATE_DIRS = [ BASE_DIR / "ABC/templates/ABC", # do NOT do this os.path.join(BASE_DIR, 'ABC/jstemplates/ABC'), # do it this way ]
The JSTEMPLATE_EXTS
section of your settings.py
tells the django-jstemplate
app what file name extensions to look for. By default ".mustache"
and ".html"
are used. The django-jstemplate
app will pick up both of these unless you tell it otherwise. Personally, I don't like my mustache template files to be ".html"
as think it should be obvious what they are. Of course, if that doesn't bother you then you can ignore this section. An example JSTEMPLATE_EXTS
section might look like:
JSTEMPLATE_EXTS = [ 'mustache', ]
Your settings.py
needs a line detailing the character set of the files it will be opening. This is actually an older, deprecated, Django setting and is not really a django-jstemplate
thing. The problem is that because Django assumes UTF-8 by default, many settings.py
files do not contain this information. The django-jstemplate
app does not assume that default and so you must specify it or you will get an error like: ImproperlyConfigured at /ABC/ FILE_CHARSET setting is required
. Below is an example -just add it to your settings.py
and you will fix the problem:
FILE_CHARSET = 'utf-8'
Your Django template file (the HTML file) needs a line loading the jstemplate
app. If it is not present you will get an error like: Invalid block tag on line xx: 'mustachejs', expected 'endblock'. Did you forget to register or load this tag
. Below is an example of the top of a Django template with the appropriate line included:
{% extends "ABC/ABC_base.html" %} {% load static %} {% load jstemplate %} {% load ABC_tags %}Of course, you also need the
mustache.min.js
engine available on the page. See the section above that discusses this.
At last we get to the actual usage of Mustache to load HTML templates. The template can be loaded by placing a line like the one below in the body of the HTML on the page.
{% mustachejs "test1" %}If the configuration of the
settings.py
file is correct and you have a file named test1.mustache
in one of the directories pointed at by the JSTEMPLATE_DIRS
setting, the file should load. At this point the text is just un-rendered HTML markup and it will be stored in the Mustache.TEMPLATES
object as a string. The text of the test1.mustache
file will be accessible as Mustache.TEMPLATES.test1
. If the template cannot be found you will see an error like: JSTemplateNotFound at /ABC/
.
For debugging purposes you can check the content is present by setting up something like the following in JavaScript:
<script> $(document).ready(function() { alert(Mustache.TEMPLATES.test1); }); <script>
Following the online documentation for the django-jstemplate
app, let us assume the HTML on the page contains an element like:
<div id="dynamic-area"></div>Furthermore, lets assume the content of the
test1.mustache
file is as shown below:
<div> <p>This is {{ name }}'s template</p> </div>Down in our JavaScript we can render and insert the text as follows (this assumes the
test1.moustache
file has previously been loaded):
<script> $(document).ready(function() { var dataObj = { name : "Joe", }; var $area = $('#dynamic-area'); $area.html(Mustache.to_html(Mustache.TEMPLATES.test1, dataObj)); }); <script>This will replace substitute in the
{{ name }}
variable and the inner HTML content of the DIV element with the id of dynamic-area
will get rendered text like ...
<div> This is Joe's template </div>... and you should see something like "This is Joe's template" appear on the web page. The problem here is that the example in the online documentation does not pass in an object which has a
name
field. This is shown below:
<script> $(document).ready(function() { var $area = $('#dynamic-area'); $area.html(Mustache.to_html(Mustache.TEMPLATES.test1)); }); <script>The above code will generate an error of
mustache.min.js:1 Uncaught TypeError: Cannot read property 'name' of undefined
. All that is really happening here is that there is no object with a name
field for the mustache.js software to substutute. Easy enough to fix - but the error message is not so simple for the inexperienced to interpret.
The online documentation also illustrates another method of rendering the template text. It looks something like the code shown below:
<script> $(document).ready(function() { var template = Mustache.template('test1'); $area.html(template.render()); }); <script>This appears to generate an error of
Uncaught TypeError: Mustache.template is not a function
. I am not at all sure of what is going on here and (to be honest) I don't much care. The previous Mustache.to_html
method is sufficient for my needs and I did not put much time into trying to resolve this error.
The contents of this web page are provided "as is" without any warranty of any kind and without any claim to accuracy. Please be aware that the information provided may be out-of-date, incomplete, erroneous or simply unsuitable for your purposes. Any use you make of the information is entirely at your discretion and any consequences of that use are entirely your responsibility. All source code is provided under the terms of the MIT License.