One great feature of a well-structured website is the navigation bar or location bar, better known as breadcrumbs. It always tells the user, where exactly s/he is currently on the website. (On the website you are currently browsing it is located above the footer, called 'Your way'.)
As a matter of fact, this bar never was easy to create. But when you use Django you don't need one single line of code to achieve your own breadcrumb navigation bar.
A Good Template Structure is the Key
Like everything in Django, you have to consider before you do something, this will save you a lot of time and nerves.
So your template structure must be well chosen. Usually, you have a file called base.html in your template-root (commonly located at /projectpath/templates/). Now all your application templates extend this file ({% extends "base.html" %}). What if you'd create one base.html for each application?
Your structure would look something like this:
project
|- templates
|- application
- base.html
- model_index.html
- base.html
Now the first line of model_index.html is {% extends "application/base.html %}, so it inherits from the application-base. The application-base in turn inherits from the root base.html ({% extends "base.html" %}). This is, what happens, when model_index.html is called:
model_index.html
↑ application/base.html
↑ base.html
Do you recognise something? This is very similar to our breadcrumb location bar, e.g. 'Start » Weblog » Entry Title'.
Django Templates Inheritance
Django's template system enables us to define named blocks ({% block breadcrumb %}{% endblock %}). When we use {% extends "base.html" %} our 'child'-template will be able to overwrite this block.
# TITLE: Template inheritance
Just overwriting would destroy the structure, because the block would only hold the last change, in our example the contents, which were defined in model_index.html.
To avoid this, Django provides the ability to access the contents of the 'parent'-template. Just use the value {{ block.super }} in a block and you will have access to the parent.
Okay, this was a long explanation, an example helps more, I guess:
<!-- base.html -->
<html>
<head>
<title>{% block head_title %}mysite.com{% endblock %}</title>
</head>
<body>
</body>
</html>
<!-- application/model_index.html -->
{% extends "base.html" %}
{% block head_title %}{{ object.title|title }} – {{ block.super }}{% endblock %}
<!-- result, when {{ object.title }} was "My test entry" -->
<html>
<head>
<title>My Test Entry – mysite.com</title>
</head>
<body>
</body>
</html>
I guess it is obvious how the inheritance work in Django templates.
Writing the Templates for breadcrumb Location Bar
Now it is pretty easy, I guess, therefore I start with the examples:
<!-- application/model_index.html -->
{% extends "application/base.html" %}
{% block breadcrumb %}{{ block.super }} » {{ object.title|title }}{% endblock %}</textarea>
<!-- application/base.html -->
{% extends "base.html" %}
{% block breadcrumb %}{{ block.super }} » <a href="/application/">Application</a>{% endblock %}</textarea>
<!-- base.html -->
<html>
<head>
<title>Breadcrumps Location Bar</title>
</head>
<body>
<div id="breadcrumbs">
{% block breadcrumb %}<a href="/">Home</a>{% endblock %}
</div>
</body>
</html>
<!-- result, when {{ object.title }} was "My test entry" -->
<html>
<head>
<title>Breadcrumps Location Bar</title>
</head>
<body>
<div id="breadcrumbs">
<a href="/">Home</a> » <a href="/application/">Application</a> » My Test Entry
</div>
</body>
</html>
What happens? The template application/model_index.html is called. It extends the template application/base.html and sets the block breadcrumbs to the title, and leaves place for the parent's breadcrumbs-content. application/base.html in turn extends base.html and leaves place for its contents.
Structures within Applications
I guess the main plot is clear now. Of course, there are more dimensions possible, like in my Photo Gallery. Here I have within the application two models with OneToMany-relation. Because each Event can have multiple Photos, so the breadcrumbs navigation bar have to look like this: Home » Gallery » Event » Photo Title. The Point is just to add base.html-templates. Here is the structure for this example:
gallery/photo_detail.html
↑ gallery/base_photo.html
↑ gallery/base_event.html
↑ gallery/base.html
↑ base.html
I guess it is obvious, what happens here: base.html adds Home, gallery/base.html adds Gallery, gallery/base_event.html adds Event Title, gallery/base_photo.html adds nothing yet, could add date (like at the current page, see right above the footer), gallery/photo_detail.html adds the Photo Title.
That's it, I guess. Questions? Suggestions? Please use the Comment form below.


Comments
cornelius commented, on October 26, 2007 at 1:11 p.m.:
Great idea, thanks for the tip.
Tony commented, on November 4, 2007 at 3:04 p.m.:
Thanks a lot for this, clean and concise - I've been using django for 2 years and didn't know about {{block.super}}!
Mackenzie commented, on March 14, 2008 at 8:01 a.m.:
This is very helpful I was just looking for a good way of doing a breadcrumb in Django. Thanks!!!!
Yeago commented, on May 7, 2008 at 8:01 p.m.:
block.super is pretty cool. I don't know about for bread crumbs, however.
One problem with it is that the current-level breadcrumb remains a link.
david commented, on May 23, 2008 at 1:46 p.m.:
Well, I know this must be the most off topic question ever but: does anyone know a TextMate theme that colours code like you are doing it in this page? I'm tired of the included ones, that either don't know what to do of the django code, or print all HTML in the same colour.
Thanks in advance
Martin Geber commented, on May 25, 2008 at 10:15 p.m.:
Hey,
@david: I don't use TextMate, sorry. But I'm also looking for Django-template syntax highlighting. (This side uses [pygments](http://pygments.org/), maybe this helps you a bit.)
@Yeago: This isn't a real problem, for example:
Home > Pictures > My and Family
Home > Pictures > All
The point is that you have to put the "All" in the main level, so "Pictures" really is linked to the very same page the user is browsing, but I guess that this is no problem.