Making a global navigation autocomplete

This guide demonstrates how to make a global navigation autocomplete like on or facebook.

There is a living example in test_project/navigation_autocomplete, which this page describes.

Note that there are many ways to implement such a feature, we’re just describing a simple one.

A simple view

As we’re just going to use autocomplete.js for this, we only need a view to render the autocomplete:

from django import shortcuts
from django.db.models import Q
from django.contrib.auth.models import User, Group

from cities_light.models import Country, Region, City

def navigation_autocomplete(request,

    q = request.GET.get('q', '')
    context = {'q': q}

    queries = {}
    queries['users'] = User.objects.filter(
        Q(username__icontains=q) |
        Q(first_name__icontains=q) |
        Q(last_name__icontains=q) |
    queries['groups'] = Group.objects.filter(name__icontains=q)[:3]
    queries['cities'] = City.objects.filter(search_names__icontains=q)[:3]
    queries['regions'] = Region.objects.filter(name_ascii__icontains=q)[:3]
    queries['countries'] = Country.objects.filter(name_ascii__icontains=q)[:3]


    return shortcuts.render(request, template_name, context)

And a trivial template (test_project/navigation_autocomplete/templates/navigation_autocomplete/autocomplete.html):

{% load url from future %}

{% for country in countrys %}
<a class="div choice" href="{% url 'admin:cities_light_country_change' %}">{{ country }}</a>
{% endfor %}
{% for region in regions %}
<a class="div choice" href="{% url 'admin:cities_light_region_change' %}">{{ region }}</a>
{% endfor %}
{% for city in cities %}
<a class="div choice" href="{% url 'admin:cities_light_city_change' %}">{{ city }}</a>
{% endfor %}
{% for group in groups %}
<a class="div choice" href="{% url 'admin:auth_group_change' %}">{{ group }}</a>
{% endfor %}
{% for user in users %}
<a class="div choice" href="{% url 'admin:auth_user_change' %}">{{ user }}</a>
{% endfor %}

And of course a url:

from django.conf.urls import patterns, url

urlpatterns = patterns('navigation_autocomplete.views',
    url(r'^$', 'navigation_autocomplete', name='navigation_autocomplete'),

A basic autocomplete configuration

That’s a pretty basic usage of autocomplete.js (test_project/navigation_autocomplete/templates/navigation_autocomplete/script.html):

{% load url from future %}

<script type="text/javascript">
$(document).ready(function() {
        url: '{% url 'navigation_autocomplete' %}',
        choiceSelector: 'a',
    }).input.bind('selectChoice', function(e, choice, autocomplete) {
        document.location.href = choice.attr('href');

Which works on such a simple input (test_project/navigation_autocomplete/templates/navigation_autocomplete/input.html):

<input type="text" name="q" id="navigation_autocomplete" style="width: 270px; font-size: 16px;" />
<style type="text/css">
    /* cancel out django default for now, or choices are white on white */
    #header a.choice:link, #header a.choice:visited {
        color: black;

See how admin/base_site.html includes them:

{% extends "admin/base.html" %}
{% load i18n %}

{% block extrahead %}
    {# These are needed to enable autocompletes in forms #}
    <script src="{{ STATIC_URL }}jquery.js" type="text/javascript"></script>
    {% include 'autocomplete_light/static.html' %}

    {% if user.is_authenticated %}
        {# This script enables global navigation autocomplete #}
        {# refer to the docs about global navigation autocomplete for more information #}
        {% include 'navigation_autocomplete/script.html' %}
    {% endif %}
{% endblock %}

{% block branding %}
    <h1 style="display: inline-block" id="site-name">{% trans 'Autocomplete-light demo' %}</h1>

    {% if user.is_authenticated %}
        {% comment %}
        This is a simple input, used for global navigation autocomplete. It
        serves as an example, refer to the documentation to make a navigation

        FYI It leaves in test_project/navigation_autocomplete/templates
        {% endcomment %}
        {% include 'navigation_autocomplete/input.html' %}
    {% endif %}
{% endblock %}