Easily add search functionality to Django projects
Switch branches/tags
Clone or download

README.md

django-find

Build Status Coverage Status Code Climate Documentation Status

Summary

django-find is a Django app that makes it easy to add complex search functionality for the models in your project. It supports two different ways to search your Django models: Query-based, or JSON-based.

django-find is not a full text search engine, it searches the fields of your models. In other words, it searches and provides tabular data.

Query-based search

By query-based, we mean that you can use statements like these to search your model:

  • hello world (searches all fields for hello and world)
  • author:robert OR title:road (searches the field "author" for "robert", and "title" for "road")
  • author:"robert frost" and (title:road or chapter:2)
  • ^robert (find anything that starts with "robert")
  • robert$ (find anything that ends with "robert")
  • ^robert$ and not title:road (find anything that equals "robert" and not the title "road")

In other words, you can write anything from super-simple text based searches, to complex boolean logic.

JSON-based search

To make it easy to do complex searches spanning multiple models, another method is provided. For example, you may want to allow for custom searches that let the user choose which models and columns to include. In other words, a user interface like this:

Custom Search

For this, a JSON-based search functionality is provided:

{
    "Author":{"name":[[["equals","test"]]]},
    "Book": {"title":[[["notcontains","c"]]]},
    "Chapter": {"content":[[["startswith","The "]]]}
}

django-find is smart in figuring out how to join those models together and return a useful result.

Quick start

Enabling the functionality is as simple as adding the "Searchable" mixin. Example:

from django.db import models
from django_find import Searchable

class Author(models.Model, Searchable):
    name = models.CharField("Author Name", max_length=10)

class Book(models.Model, Searchable):
    author = models.ForeignKey(Author, on_delete=models.CASCADE, verbose_name='Author')
    title = models.CharField("Title", max_length=80)
    rating = models.IntegerField("Rating")
    internal_id = models.CharField(max_length=10)

That is all, your models now provide the following methods:

# Query-based search returns a standard Django QuerySet that you
# can .filter() and work with as usual.
query = Book.by_query('author:"robert frost" and title:"the road"')

# You can also get a Django Q object for the statements.
q_obj = Book.q_from_query('author:"robert frost" and title:"the road"')

# JSON-based search exhausts what Django's ORM can do, so it does
# not return a Django QuerySet, but a row-based PaginatedRawQuerySet:
query, field_list = Book.by_json_raw('''{
    "Chapter": {"title":[[["contains","foo"]]]}
}''')
print('|'.join(field_list))
for row in query:
    print('|'.join(row))

You can pass the PaginatedRawQuerySet to Django templates as you would with a Django QuerySet, as it supports slicing and pagination.

Documentation

Full documentation, including installation instructions, is here:

http://django-find.readthedocs.io