9. Home pages

Robert Crowther Feb 2022
Last Modified: Mar 2022

PrevNext

If you have webpages and lists working, it’s annoying not have a homepage. At some point, as you develop CSS and menus, no homepage will stall development. What we need is a template and a view. There are several approaches.

Here is the question to ask. What is your homepage, or what would you like it to be, fundamentally? Is it little more than a page from the site? Before you leap at me and yell about being ‘professional’, most Wikis and Blogs have homepages that are no more than a modified page from the site, and this can be a quick fix for development—work on the homepage later. Or are you thinking about a page of speciality HTML, like the front page of a book? In which case, you need only a view, template, and a URL path. But many homepages nowadays are hulking mini‐apps, displaying selected content from the website, featuring extra navigation, crediting sponsors, and leading with premium advertising space. In which case you may be better building a Homepage app.

Use an existing page ‐ the quick fix

Put something like this in urls.py, as the last entry in ‘urlpatterns’,

urlpatterns = [
    ...
    path('',  SiteReviewDetailView.as_view(), {'pk':'1'}),
]

This uses a Django URL trick, that you can pass parameters to a view using a trailing dictionary.

Use a generic page

Step 12 of this guide covers Generic Pages. Using a generic page is a fairly useful solution—you’ll not be able to put any active material on the page, but at least you will be able to customise the Homepage with a title, special text, and maybe some links. For some sites, may be all you need.

In which case, you need only to create the page then, as above, make a new URL route,

urlpatterns = [
    ...
    path('',  GenericPage.as_view(), {'pk': '7'}),
]

If your generic pages are made using Djangos ‘flatpage’ app, you can substitute in a special template. Well, you could do that anyway by URLing into a custom view, like a TemplateView, then recovering interesting information and custom templating. I’ve tried these solutions, and find them too twisted. If I start wanting to make a homepage like that, I make an app—see next section.

Custom Homepage

You need is a template, a view and a URL. Personally, I prefer the dedicated app version below.

Make a lightweight ‘App’

‘Lightweight’ because it has no migrations or database tables. It has no need to be registered (your choice). But it’s encapsulated, and portable between Django instances.

Make a directory in the site, same level as other apps,

mkdir -p siteName/homepage/templates

Add the files we need,

touch siteName/homepage/views.py
touch siteName/homepage/templates/homepage.html

Note there is no namespacing subfolder in the template folder.

Well, we could make an apps.py file, and write a config, and register in settings.py. But Django doesn’t need any of that. All it needs is to call the view, and see the template. We’ll take that route.

Make a view. I’ve not mentioned these kinds of views before. A TemplateView takes a context and puts it into a template. It lacks the convenience of automatically gathering data from a DB model, but is flexible. In siteName/homepage/views.py,

from django.views.generic.base import TemplateView


class HomepageView(TemplateView):
    template_name = "homepage.html"

    def get_context_data(self, *args, **kwargs):
        ctx = super().get_context_data(*args, **kwargs)
        #self.template_name = 'site_pages/' + ctx['slug'] + '.html'
        ctx['title'] = "Home"
        ctx['news'] = "latest here"
        ctx['categories'] = "latest here"
        return ctx

Make a template in siteName/homepage/templates/homepage.html e.g.

{% extends "base.html" %}

{% block content %}
    <article class="review-typeblock">
        <h1>Welsome</h1>
        <p>We jabber</p>
        <!-- if you have data from a view, start templating
        <div>{{ news }}</div>
        <div>{{ categories }}</div>
        -->
    </article>
{% endblock %}

Alter siteName/settings.py so the template engine can find the new template directory,

TEMPLATES = [
    {
        ...
        'DIRS': [
                ...
                BASE_DIR / 'homepage' / 'templates',
        ],
]

Alter sitename/urls.py. Note that this should be usually the last of the conventional paths i.e. ‘If other matching paths fail, check the path is not empty—if it is, render the homepage’,

from homepage.views import HomepageView

urlpatterns = [
    ...
    path('',  HomepageView.as_view()),
]

Easy to find, easy to modify. You can add to it all the JavaScript, search‐bars, grid displays, weather reports, latest posts and adverts that designers love to pack into homepages.

Adding instance data to a homepage

You can add data to the view. Maybe you want to add a link to the latest review? Add to homepage/views.py,

from reviews.models import Review
...

class HomepageView(TemplateView):
    template_name = "homepage.html"

    def get_context_data(self, *args, **kwargs):
        ...
        ctx['review_latest'] = Review.objects.latest('date')
        return ctx

This is when I can cheer for Django. Clunky, yes, but clean and fast too.

Further styling

I do not intend to go into JS/CSS, that’s for you to do. However, you may have templating choices to make.

Let’s say your front page contains repeated material, particularly for items such as ‘Latest news’ or ‘Latest reviews’. The context will supply a sequence of similar objects. Django has features to help. First, in the template, you can loop, with for…next, querysets of information. That will do for a simple list of information. Also, nowadays, people like to load such lists with images, slugline/teasers, and supplementary information such as authors and prices. Depends on the site. In this case, you may need supplementary templates to structure the information from the objects, Go look at the Django templating info again.