In the previous Understand Django article, we looked at the fundamentals of using views in Django. This article will focus on templates. Templates are your primary tool in a Django project for generating a user interface. Let’s see how templates hook into views and what features Django provides with its template system.
We need a place for templates to live. Templates are static files that Django will fill in with data. In order to use those files, we must instruct Django on where to find them.
Like most parts of Django, this configuration is in your project’s settings file. After you use startproject
, you can find a section in your settings file that will be called TEMPLATES
. The section should look something like:
# project/settings.py
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
Django’s template system can use multiple template backends. The backends dictate how your templates will work. I would recommend sticking with the default Django template language. This language has the tightest integration with the framework and the strongest support.
The next thing to notice is APP_DIRS
with its value of True
. For the Django template language, setting this value to True
will cause Django to look for template files within a templates
directory in each Django application in your project. Note that this also includes any third party applications so you should probably leave this to True
.
So, where should your templates go? There are different schools of thought in the Django community. Some developers believe in having all templates within applications. Others ascribe to having all your project’s templates in a single directory. I’m in this second category of developers. I find it valuable to keep all of the templates for my entire project within a single directory.
From my perspective, keeping templates in a single directory makes it very clear where all the layout and UI in your system will live. To use that pattern, we must set the DIRS
variable with the directory that we want Django to include. I recommend keeping a templates
directory at the root of your project. If you do that, your DIRS
value will change to something like:
# project/settings.py
TEMPLATES = [
...
"DIRS": [os.path.join(BASE_DIR, "templates")],
...
]
Finally, there is OPTIONS
. Each backend can accept a variety of options. startproject
set a number of context processors. We’ll come back to context processors later in this article.
With your templates set up, you’re ready to go!
Django builds your user interface by rendering a template. The idea behind rendering is that dynamic data is combined with a static template file to produce a final output.
To produce an HttpResponse
that contains rendered output, we use the render
function. Let’s see an example.
# application/views.py
from django.shortcuts import render
def a_template_view(request):
context = {'name': 'Johnny'}
return render(request, 'hello.txt', context)
In this example, the view would use a template located in templates/hello.txt
which could contain:
Hello {{ name }}
When this view responds to a request, a user would see “Hello Johnny” in their browser. There are some interesting things to note about this example.
some_template.html
, but the Django template system can render on any type.{{ name }}
for the literal value of “Johnny” that was in the context.This idea of mixing context and static layout is the core concept of working with templates. The rest of this article builds on this root concept and shows what else is possible in the Django template language.
From the last article, you may recall seeing the TemplateView
. In those examples, we provided a template name, and I declared that Django would take care of the rest. Now you can start to understand that Django takes the template name and calls code similar to render
to provide an HttpResponse
. Those examples were missing context data to combine with the template. A fuller example to replicate what is above would look like:
# application/views.py
from django.views.generic.base import TemplateView
class HelloView(TemplateView):
template_name = 'hello.txt'
def get_context_data(self, *args, **kwargs):
context = super().get_context_data(*args, **kwargs)
context['name'] = 'Johnny'
return context
This example uses get_context_data
so that we can insert our “dynamic” data into the rendering system to give us the response we want.
In a real application, a lot of the code that we need to write focuses on building up a truly dynamic context. I’m using static data in these examples to keep the mechanics of the template system clear. When you see me use context, try to imagine more complex data building to create a user interface.
Those are the fundamentals of rendering. We’ll now turn our attention to what the Django template language is capable of.
#user interfaces #django