Breadcrumbs In Django With Templates

Written by Martin Geber on October 25, 2007 at 11:33 p.m. Filed unter: DjangoUsability.  4 Comments. Trackback URL.

Contents

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.

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 }} &amp;ndash; {{ block.super }}{% endblock %}

<!-- result, when {{ object.title }} was "My test entry" -->
<html>
    <head>
        <title>My Test Entry &amp;ndash; 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 }} &amp;raquo; {{ object.title|title }}{% endblock %}</textarea>

<!-- application/base.html -->
{% extends "base.html" %}
{% block breadcrumb %}{{ block.super }} &amp;raquo; <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> &amp;raquo; <a href="/application/">Application</a> &amp;raquo; 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.

In result you have:

project
    |- templates
        |- application
            - base.html
            - model_index.html
        - base.html
Home
<!-- 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 }} &amp;ndash; {{ block.super }}{% endblock %}

<!-- result, when {{ object.title }} was "My test entry" -->
<html>
    <head>
        <title>My Test Entry &amp;ndash; mysite.com</title>
    </head>
    <body>
    </body>
</html>
Application
<!-- application/model_index.html -->
{% extends "application/base.html" %}
{% block breadcrumb %}{{ block.super }} &amp;raquo; {{ object.title|title }}{% endblock %}</textarea>

<!-- application/base.html -->
{% extends "base.html" %}
{% block breadcrumb %}{{ block.super }} &amp;raquo; <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> &amp;raquo; <a href="/application/">Application</a> &amp;raquo; My Test Entry
        </div>
    </body>
</html>
My Test Entry.
model_index.html
    ↑ application/base.html
        ↑ base.html
Congratulations!

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

The comments also include all Trackbacks.

#1

cornelius commented, on October 26, 2007 at 1:11 p.m.:

Great idea, thanks for the tip.

 
#2

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}}!

 
#3

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!!!!

 
#4

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.

 
Post a Comment


Or

Your Way: Home » Thoughts » 2007 » October » Thursday, 25 » Breadcrumbs In Django With Templates