Skip to content


Subversion checkout URL

You can clone with
Download ZIP
Hierarchical navigation plugin for Django
Branch: master

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.

Django-navi - Navigation plugin for Django

This plugin provides means to structure a Django project in a more hierarchical manner. This makes it possible to abstract out and separate certain functionality such as authentication and authorization and outlook of navigation. In addition it automates certain functionality, such as generation and translation of URLs and navigation, altogether.

Project Structure

A project using this plugin may be structured as follows:

  • /<django project>
  • /<django project>/app
  • /<django project>/app/
  • /<django project>/app/
  • /<django project>/app/
  • /<django project>/app/
  • /<django project>/app/templates
  • /<django project>/app/<base>/<base>/.../[,]

Plugin Initialization

In addition the plugin has to be initialized at the app and like this:

from django.conf.urls.defaults import patterns
from navigation import urls
from navigation.structure import Navigation

urlpatterns = patterns('',
    (r'^login/$', 'django.contrib.auth.views.login',
        {'template_name': 'login.html'}),

navigation = Navigation()

urls.add_frontpage(urlpatterns, 'app.views.frontpage')
urls.add_navigation(urlpatterns, navigation, 'app.views')

from django.http import HttpResponseRedirect
from django.contrib.auth.decorators import login_required
from django.utils.translation import ugettext as _
from navigation import views

FRONT_PAGE = '/index/'

def page(request, template_name):
    forbidden_page = '<h1>' + _('Request denied.') + '</h1>'
    return, template_name, forbidden_page)

def frontpage(request):
    if not request.user.is_authenticated():
        return HttpResponseRedirect('/login/')

    return HttpResponseRedirect(FRONT_PAGE)

"page" is a special view that is called before any page is rendered. In this case it has been protected using login_required decorator. This means that it's not possible to access any page of the site, except for the frontpage, without logging in first.

If "page" is valid it calls the possible view function found within the application structure.


As mentioned earlier the application structure has been designed to be hierarchical. The structure is inferred directly from Python packaging.

Suppose you have defined your app as follows:

  • /app/primary
  • /app/primary/blog
  • /app/primary/gallery
  • /app/secondary

As usual each package should contain to mark it as a package. In this case __init__ is used to provide additional configuration as well. of /app/primary might look like this:

configuration = {
    'order': ('gallery', 'blog' ),

Items will be ordered alphabetically by default. In this case it has been decided that gallery should appear within the structure first.

I have listed pages and other configuration options below:

  • hidden_pages - Tuple of pages, marked hidden (this information can be used while generating user interface for navigation)
  • pages - Tuple of pages, all visible by default
  • order - Ordering of children bases. Given as a tuple.
  • exclusive_to - Django user groups to which the visibility of the base has been restricted to. Given as a tuple.
  • page_itself - Flag to set a base to be a page itself (XXX: eliminate this!)

Navigation User Interface

Note that the scheme makes it possible to generate navigation user interface quite easily. Here's a quick example of a template tag:

def get_secondary(request):
    h = HTML()
    navigation = Navigation()

    with h.ul(id="secondary_navigation"):
        if len(navigation.children) > 1:
            for page in navigation.get_navigation('secondary').children:
                    lang = translation.get_language(request)
                    name =[lang].capitalize()
                    h.a(href='/' + page.url[lang]).text(name)

    return unicode(h)


  • get rid of page_itself (if there are no children packages nor "pages", mark as page)
  • write a proper demo project (project should show how to build the project itself. Figure out how to set up virtualenv with fabric!)
  • set up requirements.txt for pip (django, pynu (get rid of lib))
  • write
Something went wrong with that request. Please try again.