Django Blog #33: Adding a Blog Search

by Alex
Django Blog #33: Adding a Blog Search
Let’s add search capabilities to the blog. Django ORM allows you to perform basic matching operations using, for example, the contains filter (or its case-sensitive version, icontains). The following query can be used to search for posts containing the word framework in the body:

from blog.models import Post.objects.filter(body__contains='framework')

But if you plan to perform complex searches with results that take into account similarities or different weights of fields, you will need a full-text search engine. Django offers a powerful search engine based on the full-text search from PostgreSQL. The django.contrib.postgres module includes features that PostgreSQL has, but that other Django-supported databases don’t. You can learn more about this search here: https://www.postgresql.org/docs/10/static/textsearch.html. While Django is capable of working with any database, it includes a module that supports a wide range of features from PostgreSQL that other databases supported by Django do not.

Simple search

Edit your project’s settings.py file and add the line django.contrib.postgres to INSTALLED_APP:

INSTALLED_APPS = [ 
   # .. 
   'django.contrib.postgres', 
]

You can now use search to perform searches:

from blog.models import Post.objects.filter(body__search='django')

This query uses PostgreSQL to create the search direction of the body field and the search query “django”. The results are based on a mapping between the direction and the query.

Search multiple fields

Sometimes you may need to search multiple fields. In this case, you need to define a SearchVector. Let’s build a vector that allows you to search in the title and body fields of the Post model:

from django.contrib.postgres.search import SearchVector 
from blog.models import Post 

Post.objects.annotate( 
    search=SearchVector('title', 'body',) 
).filter(search='django')

Using annotate and SearchVector for both fields, we get functionality that will search for matches in the title and body of posts.

Full-text search is an intensive process. If it will be performed on more than a few hundred lines, you need to define a functional index that matches the search direction you are using. Django offers a SearchVectorField for models. Read more about it here: https://docs.djangoproject.com/en/2.0/ref/contrib/postgres/search/#perfomance.

Related Posts

LEAVE A COMMENT