Adding pages to your TOM¶
The TOM Toolkit provides many views (pages) by default, but at some point you may want to add pages of your own. These could be simple static pages like project or grant information. Or they can be fully dynamic, displaying data from the database and containing forms of their own.
In this tutorial we’ll start out by adding a simple “About” page to our TOM. Then to spice it up a little we’ll add some dynamic info to the page (a list of targets). Finally we’ll learn how Django can help us create even more interactive pages.
A simple template page¶
Let’s get started with some code and we’ll explain it piece by piece afterwards.
First, let’s create a new file about.html
and place it in the
templates/
directory at the root of our TOM. This file will contain
the content of our new page.
<p>
To know that we know what we know, and to know that we do not know
what we do not know, that is true knowledge. <br/>
<strong>Nicolaus Copernicus</strong>
</p>
Next we need to tell Django about this new page and what url to serve it
from. Open the urls.py
file (next to settings.py
) and modify it
so that it looks something like this (you may have additional urls
already, the important part is the one relevant to about.html
):
from django.urls import path, include
from django.views.generic import TemplateView
urlpatterns = [
path('', include('tom_common.urls')),
path('about/', TemplateView.as_view(template_name='about.html'), name='about')
]
Notice the path
function we use here. It takes three arguments.
Argument one is the path in which this page should be made available in
our TOM. In this case, we used the sensible path “about/”. The second
argument is the view function. In this case we passed in a
TemplateView
. We’ll talk about view functions a bit later, but just know that this
class simply takes the template it should render and renders it. The
last argument is the name of the url. This is so we can refer to this
path elsewhere in the application without the need to hardcode urls.
Enough techno blabber. Launch your TOM and navigate to /about/. You should see something like this:
That’s progress, but our new page is pretty ugly. The navigation bar is
missing and we don’t have any of the nice CSS that makes the rest of the
TOM pages look good! But wait, before you start copying in lines of
HTML, know that all we need to do is extend
tom_common/base.html
to get all that back. You can read more about extending templates from
the guide on Customizing TOM
Templates. Let’s modify
about.html
to extend the base template:
{% extends 'tom_common/base.html' %}
{% block content %}
<p>
To know that we know what we know, and to know that we do not know
what we do not know, that is true knowledge. <br/>
<strong>Nicolaus Copernicus</strong>
</p>
{% endblock %}
Now when you reload the page you should see this:
Much better! By extending a template and providing a content
block,
we are able to make consistent looking pages without copying and pasting
any code.
You can read more about template inheritance in Django’s official docs
Adding in dynamic data¶
We now know how to add basic static pages. But what if we want to show
data from our database? Let’s try adding a list of all the targets in
our TOM to the about page. This is slightly more complex, so we’re going
to create a new file, views.py
alongside our urls.py
file. Add
the following content:
from django.views.generic import TemplateView
from tom_observations.models import Target
class AboutView(TemplateView):
template_name = 'about.html'
def get_context_data(self, **kwargs):
return {'targets': Target.objects.all()}
Notice we are still using the TemplateView
here. The only addition
is that we are implementing get_context_data
which returns a
dictionary of data that should be available to our template. In this
case, we are returning all the targets in our TOM.
Let’s modify our urls.py
to use our new view:
from django.urls import path, include
from .views import AboutView
urlpatterns = [
path('', include('tom_common.urls')),
path('about/', AboutView.as_view(), name='about')
]
We’ve replaced the import of TemplateView
with an import of the view
class we just wrote, and modified the call to path()
accordingly.
Lastly let’s update our about.html
template to actually show the
list of targets:
{% extends 'tom_common/base.html' %}
{% block content %}
<p>
To know that we know what we know, and to know that we do not know
what we do not know, that is true knowledge. <br/>
<strong>Nicolaus Copernicus</strong>
</p>
<ul>
{% for target in targets %}
<li>{{ target.name }}</li>
{% endfor %}
</ul>
{% endblock %}
targets
in this template refers to the key in the dictionary we
returned in the get_context_data
method in our view. We can add
anything to the context dictionary and have access to it in our
templates. In this particular example, we’re iterating over all of the
targets in our TOM and displaying all of their names. If you don’t see
anything, make sure you have targets in your TOM!
Reloading your about page, you should now see something like this:
If the page looks exactly the same as last time, you might need to add
some targets. Navigate to
http://localhost:8000/targets/
to do so. ### Class based views Django has the concept of class based
views.
These classes do one job: they take in an HTTP request and return a
response. In this tutorial we took advantage of Django’s
TemplateView
which does a simple job of rendering templates. Django has many more
built in class based
views
that can be taken advantage of. For example, instead of using the
TemplateView
for rendering a list of Targets, we could have used the
ListView
which provides additional functionality, such as pagination and
filtering.
When working with class based views, you’ll almost always subclass them.
We did this with our AboutView
earlier, and changed the
TemplateView
’s behavior to include a list of our targets. Herein
lies the power of class based views. You can even subclass the views
that ship with the TOM Toolkit itself. So for example, if you don’t like
how the
TargetListView
in the base TOM Toolkit behaves, you could subclass it in your TOM:
from tom_targets.views import TargetListView
class MyCustomTargetListView(TargetListView):
template_name = 'mysupertargetlist.html'
paginate_by = 100
Wrapping it all up¶
In this tutorial we learned how to not only add static pages to our TOM, but also how to display some information from our database. Along the way we learned about Django’s class based views as well as some of the things we could use them for.
We didn’t get into how to display forms or receive other parameters in our views, but some light reading the Django docs could familiarize one with those concepts.