Public pages: Template inheritance

  1. Templates
  2. Public pages
  3. Linking

Often, blogs will provide a means of linking to an individual post. That’s easy enough to do. We need to be a little careful of polluting our URL namespace, however. Posts can have any slug, but if we want to add new features to our web site, a post might end up interfering with those other URLs.

It is common to create a separate urls.py for each app in a project, and to make all of the features of that project start with the project’s name. For example, our archive of past postings might use the URL path /postings/archive/slug.

Add this to urls.py:

(r'^postings/', include('Blog.postings.urls')),

This will cause any URL beginning with /postings/ to be sent to urls.py in the postings folder.

In your postings folder, create a new urls.py that contains:

from django.conf.urls.defaults import *

urlpatterns = patterns('postings.views',

(r'^archive/(.+)$', 'showPost'),

)

Because this urls.py is loaded from URLs beginning with “postings/”, the showPost function is called for any URLs beginning with “postings/archive/” and then something. The stuff at the end is a regular expression. The “.” means “match any character”, the “+” means “match one or more of the previous character”. So there has to be something after the slash. It can be just about anything, but it has to be something. The parentheses mean, “send whatever this matches to the function”.

Add a new method, showPost, to views.py:

def showPost(request, postSlug):

post = get_object_or_404(Post, slug=postSlug, live=True)

context = {'post': post}

return render_to_response('post.html', context)

You can see that this function has two parameters instead of just one. The “postSlug” parameter is the stuff between the parentheses of the regular expression.

You’ll need to change the import to also import “get_object_or_404”:

from django.shortcuts import render_to_response, get_object_or_404

Currently our template’s content expects a list of posts. We could create a completely new template, but most of the time we have styled our pages so that subpages are similar. In Django, we can set up blocks of HTML that can be replaced by subpages.

Go into index.html and change the title, the headline, and the content. Everything’s the same except that we’re surrounding each section with {% block name %} and {% endblock %}.

<title>{% block title %}Old Dead Guys Blog{% endblock %}</title>

<h1>{% block headline %}The Old Dead Guys Blog{% endblock %}</h1>

<div id="content">

{% block content %}

{% for post in postings %}

<h2>{{ post.title }}</h2>

<p class="author">{{ post.author }}, {{ post.date|date:"F jS, Y h:i a" }}</p>

{{ post.content|linebreaks }}

<p class="topics">{{ post.topics.all|join:", " }}</p>

{% endfor %}

{% endblock %}

</div>

Finally, create a new file in your templates folder, “post.html”:

{% extends "index.html" %}

{% block title %}ODGB: {{ post.title }}{% endblock %}

{% block headline %}Dead Guys: {{ post.title }}{% endblock %}

{% block content %}

{{ post.content|linebreaks }}

<p class="topics">{{ post.topics.all|join:", " }}</p>

<p class="author">

<a href="{{ post.author.homepage }}">{{ post.author }}</a>,

{{ post.date|date:"l, F jS, Y h:i a" }}

</p>

<div class="bio">{{ post.author.bio|linebreaks }}</div>

{% endblock %}

You should now be able to view any individual page by going to the URL http://127.0.0.1:8000/postings/archive/slug, replacing “slug” with the slug for that posting (such as http://127.0.0.1:8000/postings/archive/hanging). Remember that if the post hasn’t been made public yet, it won’t be displayed.

  1. Templates
  2. Public pages
  3. Linking