django-navigation / docs / overview.rst

Overview

Let's assume we have this URL path:

/news/2010/oct/hello-world/

We need to convert it to :term:`breadcrumbs` and display along the heading this way:

News → 2010 news → October 2010

So we just type this in our template:

{% get_breadcrumb_trail as trail %}
<ul>
{% for crumb in trail %}
    <li><a href="{{ crumb.url }}">{{ crumb }}</a></li>
{% endfor %}
</ul>
<h1>{% breadcrumb %}</h1>

...and this is the result:

<ul>
    <li><a href="/news/>News</li>
    <li><a href="/news/2010/">2010 news</li>
    <li><a href="/news/2010/oct/">October 2010</a></li>
</ul>
<h1>Hello world</h1>

How does this work?

Current URL path is split into hierarchical parts:

* /news/
* /news/2010/
* /news/2010/oct/
* /news/2010/oct/hello-world/

For each part a :class:`navigation.helpers.Crumb` instance is created. It stores the URL and the corresponding title. But how do we know the title?

The URL title is resolved by a :term:`crumb resolver`. By default two resolvers are available: _resolve_flatpage and _resolve_by_callback.

The first one looks for a FlatPage object with given URL path in the database (if django.contrib.flatpages is activated in settings). If this resolver failed (i.e. flatpages are not available or there's no FlatPage with such URL path), then next crumb resolver is called.

The crumb resolver _resolve_by_callback peeks into the URL maps and attempts to resolve the URL into a view function. If such function is found, the resolver looks whether the function has the "breadcrumb" attribute. This attribute can be set by wrapping the view in decorator :func:`navigation.decorators.breadcrumb`:

from navigation.decorators import breadcrumb

@breadcrumb('Hello')
def say_hello(request):
    ...

@breadcrumb(lambda request: u'%s settings' % request.user)
def user_settings(request):
    ...

If the attribute is not found, we can't guess the name and give up. A dummy breadcrumb is add to the trail.

However, we could also try "humanizing" the function's __name__ attribute or use a custom path-to-name mapping. You can do that easily by creating your own crumb resolvers and registering them this way:

from navigation.resolvers import crumb_resolver

@crumb_resolver
def my_custom_resolver_function(request, url):
    return Crumb(url, 'Hello!')

TODO

I'll probably make this more explicit, e.g. add a settings variable like this:

NAVIGATION_RESOLVERS = [
    'navigation.resolvers.resolve_flatpage',
    'navigation.resolvers.resolve_by_callback',
    'utils.navigation.my_custom_resolver_function',
]
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.