Full text search in Django
This is a basic, but hopefully complete example of an implementation of full text search in Django using PostgreSQL. This can be used as an alternative to Elasticsearch with Haystack, which is a popular solution for this problem. Despite how awesome Elasticsearch is, it might be overkill for many cases.
This requires at least Django 1.10 and it was tested on PostgreSQL 9.6. It assumes that you know your way around both technologies.
Let’s say we have a simple model like this:
{% highlight python %} from django.db import models
class Person(models.Model): first_name = models.CharField(max_length=150) last_name = models.CharField(max_length=150) address = models.CharField(max_length=150) {% endhighlight %}
And we want to search by first_name, last_name or address.
First, make sure that django.contrib.postgres
is in INSTALLED_APPS
.
Next, we need a simple form to submit the search terms:
{% highlight html %} {% raw %}
And a very simple template to show the results:
{% highlight html %} {% raw %}
{% extends “base.html” %}
{% endraw %} {% endhighlight %}
Now, we add the url in urls.py
:
{% highlight python %} url(r’^search/’, views.SearchView.as_view(), name=‘search’), {% endhighlight %}
Finally, let’s write the View. A simple ListView will do the trick:
{% highlight python %} from django.contrib.postgres.search import SearchVector from django.views.generic.list import ListView
class SearchView(ListView):
template_name = 'results.html'
context_object_name = 'persons'
def search_persons(self, query):
results = Person.objects.annotate(
search=SearchVector('first_name',
'last_name',
'address')).
filter(search=query)
return results
def get_queryset(self):
query = self.request.GET.get('q')
persons = self.search_persons(query)
return persons
{% endhighlight %}
Full text search is a complex and fascinating subject, this is only a trivial example. Django documentation on this subject is here and the excellent PostgreSQL docs are here.