Martin Geber
Martin is student at EUFH, Cologne, DE
working casually at DataCollect & EWE
who loves economies, web-technology
and all things J.K. Rowling.
Learn More.
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.
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'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 }} &ndash; {{ block.super }}{% endblock %} <!-- result, when {{ object.title }} was "My test entry" --> <html> <head> <title>My Test Entry &ndash; mysite.com</title> </head> <body> </body> </html>
I guess it is obvious how the inheritance work in Django templates.
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 }} &raquo; {{ object.title|title }}{% endblock %}</textarea> <!-- application/base.html --> {% extends "base.html" %} {% block breadcrumb %}{{ block.super }} &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> &raquo; <a href="/application/">Application</a> &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
<!-- 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 }} &ndash; {{ block.super }}{% endblock %} <!-- result, when {{ object.title }} was "My test entry" --> <html> <head> <title>My Test Entry &ndash; mysite.com</title> </head> <body> </body> </html>
<!-- application/model_index.html --> {% extends "application/base.html" %} {% block breadcrumb %}{{ block.super }} &raquo; {{ object.title|title }}{% endblock %}</textarea> <!-- application/base.html --> {% extends "base.html" %} {% block breadcrumb %}{{ block.super }} &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> &raquo; <a href="/application/">Application</a> &raquo; My Test Entry </div> </body> </html>
model_index.html
↑ application/base.html
↑ base.html
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.
Thanks a lot for this, clean and concise - I've been using django for 2 years and didn't know about {{block.super}}!
This is very helpful I was just looking for a good way of doing a breadcrumb in Django. Thanks!!!!
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.
Python Code is Poetry
© Copyright 1987-2008
Martin Geber
Django | XHTML 1.1 | CSS | Imprint
cornelius commented, on October 26, 2007 at 1:11 p.m.:
Great idea, thanks for the tip.