Autocomplete with Django Haystack, Solr and JQuery: a Quick Guide

by Applied Informatics

Ever wondered how to add autocomplete to your web application, here’s your chance to get wet 🙂

Most sites have built-in search compatibilities, and are increasingly becoming associated with autocomplete. To implement this cool add-on to a Django application, we will use Haystack.

First let’s install Django-Haystack. A few requirements need to be met.

  • Django 1.6+
  • Python 2.7+ or Python 3.3+
  • Solr 5 is NOT compatible (IMPORTANT)

As noted, Solr 5 is not compatible with Haystack just yet. For this tutorial, we will be using Solr 4.10.2.

Step 1: Setup Solr

Download Solr 4.10.2 and unpack the directory to a location of your choosing.

Go into the the unpacked directory and start the solr server.

$ cd solr-4.10.2/bin/

Start the Solr Engine

$ solr start

(default port is :8983)

To stop Solr at anytime

$ solr stop

(to start/stop one server: -p)

(to start/stop all server: -all)

Step 2: Index and prepare data

Autocomplete uses n-grams to store your data. Think n-grams as each individual character in your string that needs to be matched with the user input.

In your SearchIndex add a new field containing the test that requires autocomplete.

For most uses, EdgeNgramField is suitable and tokenizes on whitespace. This prevents incorrect matches when part of two different words are mashed together as one n-gram.

Example:

from haystack import indexes
from myapp.models import Note

class MovieIndex(indexes.SearchIndex, indexes.Indexable):
    title = indexes.CharField(document=True, use_template=True)
    director = indexes.CharField(model_attr='director')
    rating = indexes.CharField(model_attr='rating')
    # add this for autocomplete.
    actor_auto = indexes.EdgeNgramField(model_attr='actor')

    def get_model(self):
        return Movie

    def index_queryset(self, using=None):
        """Used when the entire index for model is updated."""
        return Movie.objects.filter(outNow = True)

After ALL schema changes, rebuild/update your index:

$ python manage.py rebuild_index

Then go back into your Solr Engine. After every rebuild, the engine stops, so now it needs to be started up again.

Step 3: Perform Query

With Haystack, all we have to use is the built-in SearchQuerySet.autocomplete method. Just provide the field and query.

Here is an example in views.py:

import json
from django.http import HttpResponse
from haystack.query import SearchQuerySet

def autocomplete(request):

    actor_auto= SearchQuerySet().autocomplete(actor_auto=request.GET.get('q', ''))[:5]
    suggestions = [result.title for result in actor_auto]
    data = json.dumps({
        'results': suggestions
    })
    return HttpResponse(data, content_type='application/json')

Step 4: Add Autocomplete URL to urls.py

Check your search queries by appending the following to urls.py:
url(r^autocomplete/, autocomplete, name=autocomplete)
Go to the URL, “/autocomplete/?q= ” to check if your queries are fetching the desired results.

For example the URL, “localhost/autocomplete/?q=Matt”

Will display a list:

["Matt Dillon", "Matthew Mcconaughey", "Matt Bomer"]

Thus the query works as expected.

Step 5: Front-End

For implementing the code quickly and painlessly in the front-end, we will use jQuery UI Autocomplete. This allows to quickly find matches from a populated list of values as they type and take advantage of haystack/Solr’s search and filter capabilities. Find the id/class of your input field and use it as the selector in the jQuery function.

Example:

<script src="//code.jquery.com/jquery-1.10.2.js"></script>

<script src="//code.jquery.com/ui/1.11.4/jquery-ui.js"></script>

<script src="//jqueryui.com/jquery-wp-content/themes/jquery/js/plugins.js"></script>

<script src="//jqueryui.com/jquery-wp-content/themes/jquery/js/main.js"></script>

<link rel="stylesheet" href="//code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css">

$('#q').autocomplete({ 
	source: function (request, response) { 
		$.getJSON("/autocomplete/?q=" + request.term, function (data) { 
			response(data); 
		}); 
	} 
});

Test the Input Field. If it works, CONGRATULATIONS!!!!
If not, keep reading to Step 6!

Step 6: JSON Format

jQuery’s Autocomplete feature only likes the JSON to look in a few specific ways, so reformat your JSON response to be similar to the methods shown below.

There are a few ways to format your JSON response to ensure autocomplete renders.

Example 1:

	var availableTags = [
		"ActionScript",
		"AppleScript",
		"Asp",
		"BASIC",
		"C",
		"C++",
		"Clojure",
		"COBOL",
		"ColdFusion",
		"Erlang",
		"Fortran",
		"Groovy",
		"Haskell",
		"Java",
		"JavaScript",
		"Lisp",
		"Perl",
		"PHP",
		"Python",
		"Ruby",
		"Scala",
		"Scheme"
	];

Example 2:

	{
		source: [
			"Milan", 
			"Turin", 
			"Venice", 
			"Florence", 
			"Rome"
		] 
	}

or

[{"label":"mylabel","value":"myvalue"},...] 

In the front-end (index.html) Change your jquery code to look similar to this:

$('#q').autocomplete({
 source: function (request, response) {
	 $.getJSON("/autocomplete/?q=" + request.term, function (data) {
		 response($.map(data, function (value, key) {
			 return {
			 	label: value,
			 	value: key
			 };
		 }));
	 });
 },
 minLength: 1
});

Drop a comment and let me know your experience with adding autocomplete!

2 thoughts on “Autocomplete with Django Haystack, Solr and JQuery: a Quick Guide”

Leave a Reply to deepa Cancel reply

Your email address will not be published. Required fields are marked *

Tools & Practices

Tools and Technologies we use at Applied

Contact us now

Popular Posts