Skip to content

kaedroho/django-modelsearch

Repository files navigation

Django ModelSearch

Build Status License Version Documentation

Django ModelSearch allows you to index Django models and search them using the ORM!

It supports PostgreSQL FTS, SQLite FTS5, Elasticsearch (7.x, 8.x, and 9.x), and OpenSearch (1.x, 2.x, and 3.x).

Features:

This has been built into Wagtail CMS since 2014 and extracted into a separate package in March 2025.

Installation

Install with PIP, then add to INSTALLED_APPS in your Django settings:

pip install modelsearch
# settings.py

INSTALLED_APPS = [
    ...
    "modelsearch",
    ...
]

By default, Django ModelSearch will index into the database configured in DATABASES["default"] and use PostgreSQL FTS or SQLite FTS, if available.

You can change the indexing configuration, or add additional backends with the MODALSEARCH_BACKENDS setting. For example, to configure Elasticsearch:

# settings.py

MODELSEARCH_BACKENDS = {
    'default': {
        'BACKEND': 'modelsearch.backends.elasticsearch8',
        'URLS': ['https://localhost:9200'],
        'INDEX_PREFIX': 'modelsearch_',
        'TIMEOUT': 5,
        'OPTIONS': {},
        'INDEX_SETTINGS': {},
    }
}

Indexing

To index a model, add modelsearch.index.Indexed to the model class and define some search_fields:

from modelsearch import index
from modelsearch.queryset import SearchableQuerySetMixin


# This mixin adds a .search() method to the models QuerySet
class SongQuerySet(SearchableQuerySetMixin, models.QuerySet):
    pass


# Create a model that inherits from Indexed
class Song(index.Indexed, models.Model):
    name = models.TextField()
    lyrics = models.TextField()
    release_date = models.DateField()
    artist = models.ForeignKey(Artist, related_name='songs')

    objects = SongQuerySet.as_manager()

    # Define a list of fields to index
    search_fields = [
        # Index text fields for full-text search
        # Boost the important fields
        index.SearchField('name', boost=2.0),
        index.SearchField('lyrics'),

        # Index fields that for filtering
        # These get inserted into Elasticsearch for fast filtering
        index.FilterField('release_date'),
        index.FilterField('artist'),

        # Pull in content from related models too
        index.RelatedFields('artist', [
           index.SearchField('name'),
        ]),
    ]

Then run the django-admin rebuild_modelsearch_index to create the indexes, mappings and insert the data. Signals are then used to keep the index in sync with the database.

Searching

Search by calling .search() on the QuerySet!

Song.objects.search("Flying Whales")

Searches also work when reversing ForeignKeys:

opeth.songs.search("Harvest")

You can use Django's .filter(), .exclude() and .order_by() with search too:

Song.objects.filter(release_date__year__lt=1971).search("Iron Man")

The filters are rewitten into the Elasticsearch query to make it run fast with a lot of data.

About

Index Django Models with Elasticsearch or OpenSearch and query them with the ORM

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 87

Languages