modelsearch
A library for indexing Django models with Elasicsearch, OpenSearch or database and searching them with the Django ORM.
Description
# Django ModelSearch <p> <a href="https://github.com/wagtail/django-modelsearch/actions"> <img src="https://github.com/wagtail/django-modelsearch/workflows/ModelSearch%20CI/badge.svg?branch=main" alt="Build Status" /> </a> <a href="https://opensource.org/licenses/BSD-3-Clause"> <img src="https://img.shields.io/badge/license-BSD-blue.svg" alt="License" /> </a> <a href="https://pypi.python.org/pypi/modelsearch/"> <img src="https://img.shields.io/pypi/v/modelsearch.svg" alt="Version" /> </a> <a href="https://django-modelsearch.readthedocs.io/en/latest/"> <img src="https://img.shields.io/badge/Documentation-blue" alt="Documentation" /> </a> </p> Django ModelSearch allows you to index Django models and [search them using the ORM](https://django-modelsearch.readthedocs.io/en/latest/searching.html)! It supports PostgreSQL FTS, SQLite FTS5, MySQL FTS, MariaDB FTS, Elasticsearch (7.x, 8.x, and 9.x), and OpenSearch (2.x and 3.x). Features: - Index models in Elasticsearch and OpenSearch and query with the Django ORM - Reuse existing QuerySets for search, works with Django paginators and `django-filter` - Also supports PostgreSQL FTS, MySQL FTS, MariaDB FTS and SQLite FTS5 - [Autocomplete](https://django-modelsearch.readthedocs.io/en/latest/searching.html#autocomplete-search) - [Faceting](https://django-modelsearch.readthedocs.io/en/latest/searching.html#facet-field-name) - [Per-field boosting](https://django-modelsearch.readthedocs.io/en/latest/indexing.html#boosting-search-fields) - [Fuzzy Search](https://django-modelsearch.readthedocs.io/en/latest/searching.html#fuzzy-search) - [Phrase search](https://django-modelsearch.readthedocs.io/en/latest/searching.html#phrase-search) - [Structured queries](https://django-modelsearch.readthedocs.io/en/latest/searching.html#structured-queries) - [Multi-table inheritance](https://django-modelsearch.readthedocs.io/en/latest/indexing.html#indexing-models-with-multi-table-inheritance) - Zero-downtime index rebuilding (uses aliases to atomically swap in a new index when its ready) This has been built into [Wagtail CMS](https://github.com/wagtail/wagtail) since 2014 and extracted into a separate package in March 2025. ## Installation Install with PIP, then add to `INSTALLED_APPS` in your Django settings: ```shell pip install modelsearch ``` ```python # settings.py INSTALLED_APPS = [ ... "modelsearch", ... ] ``` By default, Django ModelSearch will index into the database configured in `DATABASES["default"]` and use PostgreSQL FTS, MySQL FTS, MariaDB FTS or SQLite FTS, if available. If you are using PostgreSQL, you must additionally add `django.contrib.postgres` to your [`INSTALLED_APPS`](https://docs.djangoproject.com/en/stable/ref/settings/#std-setting-INSTALLED_APPS) setting. You can change the indexing configuration, or add additional backends with the `MODELSEARCH_BACKENDS` setting. For example, to configure Elasticsearch: ```python # 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`: ```python 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! ```python Song.objects.search("Flying Whales") ``` Searches also work when reversing `ForeignKey`s: ```python opeth.songs.search("Harvest") ``` You can use Django's `.filter()`, `.exclude()` and `.order_by()` with search too: ```python Song.objects.filter(relea
Release History
| Version | Changes | Urgency | Date |
|---|---|---|---|
| 1.3 | Imported from PyPI (1.3) | Low | 4/21/2026 |
| v1.3 | ## New features * Add fuzzy search support to PostgreSQL backend by @fabienheureux in https://github.com/wagtail/django-modelsearch/pull/65 * Handle nested RelatedFields on Elasticsearch by @gasman in https://github.com/wagtail/django-modelsearch/pull/77 * Support filtering on related fields by @gasman in https://github.com/wagtail/django-modelsearch/pull/83 * Implement result scoring (including annotation) on sqlite by @gasman in https://github.com/wagtail/django-modelsearch/pull/85 ## B | High | 4/20/2026 |
| v1.2.1 | ## What's Changed * Correctly handle trailing hyphens in Postgres search by @gasman in https://github.com/wagtail/django-modelsearch/pull/92 * Delay import of signal handlers until app is ready by @thomasmassmann in https://github.com/wagtail/django-modelsearch/pull/87 ## New Contributors * @thomasmassmann made their first contribution in https://github.com/wagtail/django-modelsearch/pull/87 **Full Changelog**: https://github.com/wagtail/django-modelsearch/compare/v1.2.0...v1.2.1 | High | 4/16/2026 |
| v1.2.0 | ## What's Changed * Support ranking and score annotation on MySQL by @gasman in https://github.com/wagtail/django-modelsearch/pull/53 * Support TimeField on ElasticSearch by @gasman in https://github.com/wagtail/django-modelsearch/pull/52 * Various code coverage fixes (rebase of #42) by @gasman in https://github.com/wagtail/django-modelsearch/pull/55 * Correctly handle hyphenated search terms on Postgres by @gasman in https://github.com/wagtail/django-modelsearch/pull/57 * Allow version 0.1 | Low | 2/11/2026 |
| v1.1.1 | ## What's Changed * Test against Django 4.2 and 6.0b1 by @gasman in https://github.com/wagtail/django-modelsearch/pull/43 * Remove hidden _WAGTAILSEARCH_FORCE_AUTO_UPDATE setting by @gasman in https://github.com/wagtail/django-modelsearch/pull/41 **Full Changelog**: https://github.com/wagtail/django-modelsearch/compare/v1.1...v1.1.1 | Low | 11/10/2025 |
| v1.1 | ## Highlights This release brings a load of changes from @gasman to allow django-modelsearch to be used by Wagtail CMS. The main improvements are: - MySQL / MariaDB support - Add order_by argument to queryset search - Drop support for OpenSearch 1.x (EOL) - Make model available on SearchResults object ## What's Changed * Add Ruff linting by @gasman in https://github.com/kaedroho/django-modelsearch/pull/17 * Add a Vagrant VM configuration for running coverage reports by @gasman | Low | 11/4/2025 |
| v1.1rc1 | ## What's Changed * Add Ruff linting by @gasman in https://github.com/kaedroho/django-modelsearch/pull/17 * Add a Vagrant VM configuration for running coverage reports by @gasman in https://github.com/kaedroho/django-modelsearch/pull/18 * Reinstate MySQL / MariaDB support by @gasman in https://github.com/kaedroho/django-modelsearch/pull/19 * Document the need to add django.contrib.postgres to INSTALLED APPS by @gasman in https://github.com/kaedroho/django-modelsearch/pull/21 * Make model | Low | 10/24/2025 |
| v1.0 | ## Our first release! 🚀 This release marks the first stable release of `django-modelsearch` since it was forked from Wagtail search. | Low | 8/4/2025 |
| v1.0rc6 | Release v1.0rc6 | Low | 8/1/2025 |
| v1.0rc5 | Release v1.0rc5 | Low | 7/31/2025 |
| v1.0rc4 | Release v1.0rc4 | Low | 7/31/2025 |
| v1.0rc3 | Release v1.0rc3 | Low | 7/31/2025 |
| v1.0rc2 | Release v1.0rc2 | Low | 7/31/2025 |
| v1.0rc1 | Release v1.0rc1 | Low | 7/31/2025 |
