Jinja globals: Access data on all Jinja templates, like Django context processors
Just like Django templates offer
context processors to facilitate the access of data on all Django
templates, Jinja also offers its own version of the same feature
which is called globals. Jinja in its out-of-the-box state
has no globals, but in its Django integrated mode includes three
globals to mimic Django's most common context processors, these
globals are: request
, csrf_input
and
csrf_token
.
This means you get access to three Django context processor 'like variables in all Jinja templates used in Django projects. However, to set up additional global variables you need to work with Jinja's environment.
To set up Jinja globals you need
to access Jinja's environment which is where globals are stored, in
a variable properly called globals
. By default, the
Django-Jinja configuration uses Jinja's built-in
jinja2.Environment
environment. In order to access
Jinja's environment in Django and set globals, the easiest path is
to create your own Jinja environment and use it to initialize the
Django-Jinja configuration. Listing 4-11 illustrate a custom Jinja
environment class which sets the global variables named
static
and url
.
Listing 4-11 Custom Jinja environment with global variable
from jinja2.environment import Environment from django.contrib.staticfiles.storage import staticfiles_storage from django.core.urlresolvers import reverse class JinjaEnvironment(Environment): def __init__(self,**kwargs): super(JinjaEnvironment, self).__init__(**kwargs) self.globals['static'] = staticfiles_storage.url self.globals['url'] = reverse
As you can see in listing 4-11,
the custom JinjaEnvironment
class is a sub-class of
the jinja2.Environment
class, this is so the custom
class inherits the bulk of its features from this base class
provided by Jinja. Next, you can see we use the
__init__
method to initialize the base class.
Prior to exiting the
initialization method of the class, you can also see we access the
globals
variable of the instance. globals
is composed of a dictionary, where the key-values correspond to the
Jinja template variable names and values, respectively. In this
case, we create the static
variable and assigns it Django's
django.contrib.staticfiles.storage.staticfiles_storage.url
method. This gives the static
global variable the same
behavior as Django's staticfiles app, so that it's possible to
declare static resources just like it's done in Django (e.g. Jinja
can then do <img src="{{ static('images/background.png')
}}" alt="Background">
) -- a topic which is described in
greater detail in chapter 5 on static resource management, but this
is important to mention here due to the gap it fills in Jinja
lacking functionality on this front.
The second global in listing 4-11
creates the url
variable and assigns it Django's
django.core.urlresolvers.reverse
method. This gives
the url
global variable the same behavior as Django's
{% url %}
tag, so that it's possible to resolve a URL
based on a name-- as described in the chapter two section Url naming and namespaces -- just like it's done in Django
(e.g. Jinja can then do <a href="{{ url('homepage')
}}">Go to homepage</a>
) -- note this is another
important gap to fill given Jinja's lack of functionality on this
front.
Just as you can add these last two global variable to mimic the behavior of Django apps and tags that are missing in Jinja templates, you can add more globals in the same manner or increase the complexity of a Jinja global as needed.
Once the custom Jinja environment
is ready, you need to set it up in Django's
settings.py
file so it's used to initialize Jinja.
Listing 4-12 illustrates how to set up a custom Jinja environment
in Django inside the TEMPLATES
variable.
Listing 4-12. Configure custom Jinja environment in Django setttings.py
from pathlib import Path BASE_DIR = Path(__file__).resolve().parent.parent PROJECT_DIR = Path(__file__).resolve().parent TEMPLATES = [ { 'BACKEND':'django.template.backends.jinja2.Jinja2', 'DIRS': [ PROJECT_DIR / 'jinjatemplates' ], 'APP_DIRS': True, 'OPTIONS': { 'environment': 'coffeehouse.jinja.env.JinjaEnvironment' } }, ]
The Jinja environment is set
through the environment
key, as part of the
OPTIONS
variable. The value of the environment key is
a string with dot notation that points to a custom Jinja
environment class. In this case, you can see the value corresponds
to coffeehouse.jinja.env.JinjaEnvironment
, where
JinjaEnvironment
is the class, env
is the
file/module name and coffeehouse.jinja
is the
directory path.
To better illustrate the location
of the env.py
file containing the custom Jinja
environment, listing 4-13 illustrates a directory structure with
additional Django project files for reference.
Listing 4-13 Directory structure and location of custom Jinja environment
+---+-<PROJECT_DIR_coffeehouse> | +-asgi.py +-__init__.py +-settings.py +-urls.py +-wsgi.py | +-jinja-+ +-__init__.py +-env.py
A with the placement and configuration of this Jinja environment in a Django project, all Jinja templates are able to use the static
and url
globals.