Simple search in Django Simple search in Django django django

Simple search in Django


If you want a really simple search you can use icontains lookup and Q object:

from django.db.models import Qresults = BlogPost.objects.filter(Q(title__icontains=your_search_query) | Q(intro__icontains=your_search_query) | Q(content__icontains=your_search_query))

You should also note that Haystack doesn't have to be "hideously complicated". You can set up haystack with Whoosh backend in less then 15 minutes.

Update 2016: In version 1.10 Django added a full text search support (PostgreSQL only). An answer to the original question using the new module might look something like this:

from django.contrib.postgres.search import SearchVectorresults = BlogPost.objects.annotate(    search=SearchVector('title', 'intro', 'content'),).filter(search=your_search_query)

The new full text search module contains a lot more features (for example sorting by relevancy), you can read about them in the documentation.


From the Django source:

# Apply keyword searches.def construct_search(field_name):    if field_name.startswith('^'):        return "%s__istartswith" % field_name[1:]    elif field_name.startswith('='):        return "%s__iexact" % field_name[1:]    elif field_name.startswith('@'):        return "%s__search" % field_name[1:]    else:        return "%s__icontains" % field_nameif self.search_fields and self.query:    for bit in self.query.split():        or_queries = [models.Q(**{construct_search(str(field_name)): bit}) for field_name in self.search_fields]        qs = qs.filter(reduce(operator.or_, or_queries))    for field_name in self.search_fields:        if '__' in field_name:            qs = qs.distinct()            break

Clearly, it uses the database options to perform search. If nothing else, you should be able to reuse some of the code from it.

So says the documentation too: http://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.search_fields

The full text search, however, uses the MySQL index (only if you are using MySQL).


You would use the __search operator. It's documented in the Django QuerySet API Reference. There's also istartswith, which does a case-insensitive starts-with search.

Here's a working example (adapted from my own Django site):

def search(request):    try:        q = request.GET['q']        posts = BlogPost.objects.filter(title__search=q) | \                BlogPost.objects.filter(intro__search=q) | \                BlogPost.objects.filter(content__search=q)        return render_to_response('search/results.html', {'posts':posts, 'q':q})    except KeyError:        return render_to_response('search/results.html')

Note that __search is only available in MySQL and requires direct manipulation of the database to add the full-text index. See the MySQL documentation for additional details.