Full-text search refers to techniques for searching a single computer-stored document or a collection in a full-text database. Full-text search is distinguished from searches based on metadata or on parts of the original texts represented in databases (such as titles, abstracts, selected sections, or bibliographical references).

PostgresSQL Support

PostgreSQL has its own full-text search implementation built-in. While not as powerful as some other search engines, it has the advantage of being inside your database and so can easily be combined with other relational queries such as categorization.

The database functions in the django.contrib.postgres.search module ease the use of PostgreSQL’s full text search engines.

For use this tools is most easily to setup an example with a simple app into Django

Read more about postgresSQL support

Create a Model

from django.db import models

class Entity(models.Model):

    name = models.CharField(max_length=150)
    email = models.EmailField(max_length=300)
    city = models.CharField(max_length=300)
    country = models.CharField(max_length=300)
    url = models.URLField(max_length=400, blank=True)
    apply = models.BooleanField(default=False)
    description = models.TextField(blank=False)

    def __str__(self):
        return self.name

Create view function-based (in this case)

Inside to views.py

def search(request):
    pass

For now, this is basically the begin

View’s URL

Inside to urls.py

# django
from django.urls import path
# project
from .views import search

urlpatterns = [
    path('search', search, name='search'),
]

Create View Template

Into search.html file

{# This will be explain after #}
{{ count_filters }}
{% for entity in entities_filtered %}
<p>{{ entity.name }}</p>
<p>{{ entity.email }}</p>
<p>{{ entity.city }}</p>
<p>{{ entity.country }}</p>
<p>{{ entity.url }}</p>
<p>{{ entity.apply }}</p>
<p>{{ entity.description}}</p>
{% endfor %}

Now into search-form.html, we are going to create the form to actions the search view

<form action="{% url 'search' %}" method="GET">
    <input name="q" type="text" placeholder="Search">
    <button>Search</button>
</form>

SearchVector Implementation

How to use:

>>> from django.contrib.postgres.search import SearchVector
>>> Entry.objects.annotate(
...     search=SearchVector('body_text', 'blog__tagline'),
... ).filter(search='Cheese')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza Recipes>]

For more information about SearchVector.

Now in our view code that we created above.

from django.contrib.postgree.search import SearchVector

def search(request):

    # Here we get the value of the search field from the template
    q = request.GET.get('q', '').strip()

    # Here we are going to type the principal attributes
    # that we want to search in the search field form
    # in this case are: name, city, country, description,
    # and created_at
    entity_vector = SearchVector(
        'name', 'city', 'country', 'description', 'created_at'
    )

SearchQuery Implementation

How to use:

>>> from django.contrib.postgres.search import SearchQuery
>>> SearchQuery('red tomato')  # two keywords
>>> SearchQuery('tomato red')  # same results as above
>>> SearchQuery('red tomato', search_type='phrase')  # a phrase
>>> SearchQuery('tomato red', search_type='phrase')  # a different phrase
>>> SearchQuery("'tomato' & ('red' | 'green')", search_type='raw')  # boolean operators
>>> SearchQuery("'tomato' ('red' OR 'green')", search_type='websearch')  # websearch operators

For more information about SearchQuery.

Now in our view code that we created above

from django.contrib.postgree.search import (SearchVector,
    SearchQuery
)

def search(request):

    # Here we get the value of the search field from the template
    search_field_query = request.GET.get('q', '').strip()

    # Here we are going to type the principal attributes
    # that we want to search in the search field form
    # in this case are: name, city, country, description,
    # and created_at
    entity_vector = SearchVector(
        'name', 'city', 'country', 'description', 'created_at'
    )

    # Here we just pass the value of the search field query
    entity_query = SearchQuery(search_field_query)

SearchRank Implementation

How to use:

>>> from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
>>> vector = SearchVector('body_text')
>>> query = SearchQuery('cheese')
>>> Entry.objects.annotate(rank=SearchRank(vector, query)).order_by('-rank')
[<Entry: Cheese on Toast recipes>, <Entry: Pizza recipes>]

For more information about SearchRank.

Now in our view code that we created above

from django.shortcuts import render
from django.contrib.postgree.search import (SearchVector,
SearchQuery
)
from .models import Entity

def search(request):
    # This is to count how many object there are (it's optional)
    count_filters = 0

    # Here we get the value of the search field from the template
    search_field_query = request.GET.get('q', '').strip()

    # Here we are going to type the principal attributes
    # that we want to search in the search field form
    # in this case are: name, city, country, description,
    # and created_at
    entity_vector = SearchVector(
        'name', 'city', 'country', 'description', 'created_at'
    )

    # Here we just pass the value of the search field query
    entity_query = SearchQuery(search_field_query)

    # Here we pass the entity_vector and entity_query
    entities_filtered = Entity.objects.annotate(
        rank=SearchRank(entity_vector, entity_query)
    ).order_by('-rank')

    # count filters
    count_filters += entities_filtered.count()

    # Now We are going to create the context dictionary
    context = {
        'entities_filtered': entities_filtered,
        'count_filters': count_filters,
    }

    # Now we are going to complete with our view
    return render(request, 'search/search.html', context)

Search View Class-Based

The same search view, now with class:

from django.shortcuts import render
from django.views import View
from django.contrib.postgree.search import (SearchVector,
    SearchQuery
)
from .models import Entity

class SearchEntityView(View):
    template_name = 'search/search.html'

    def get(self, request, *args, **kwargs):
        count_filters = 0

        search_field_query = request.GET.get('q', '').strip()

        entity_vector = SearchVector(
            'name', 'city', 'country', 'description', 'created_at'
        )

        entity_query = SearchQuery(search_field_query)

        entities_filtered = Entity.objects.annotate(
            rank=SearchRank(entity_vector, entity_query)
        ).order_by('-rank')

        count_filters += entities_filtered.count()

        context = {
            'entities_filtered': entities_filtered,
            'count_filters': count_filters,
        }

        return render(request, self.template_name, context)

Then change the url.py path:

# django
from django.urls import path
# project
from .views import SearchEntityView

urlpatterns = [
    path('search', SearchEntityView.as_view(), name='search'),
]

If you want to read yourself from the Django docs just do it.