{"id":2122,"library":"django-modelsearch","title":"Django Model Search","description":"django-modelsearch is a Python library that enables indexing Django models with various search backends, including Elasticsearch, OpenSearch, and the database itself (PostgreSQL, MySQL). It provides a unified API for searching models, inspired by Wagtail Search. The current version is 1.2.0, with releases occurring periodically to support Django and backend updates.","status":"active","version":"1.2.0","language":"en","source_language":"en","source_url":"https://github.com/wagtail/django-modelsearch","tags":["django","search","elasticsearch","opensearch","database-search","orm","wagtail"],"install":[{"cmd":"pip install django-modelsearch","lang":"bash","label":"Base installation"},{"cmd":"pip install \"django-modelsearch[elasticsearch]\"","lang":"bash","label":"With Elasticsearch support"},{"cmd":"pip install \"django-modelsearch[opensearch]\"","lang":"bash","label":"With OpenSearch support"}],"dependencies":[{"reason":"Framework integration for models and ORM","package":"Django","optional":false},{"reason":"Required for Elasticsearch search backend","package":"elasticsearch","optional":true},{"reason":"Required for OpenSearch search backend","package":"opensearch-py","optional":true},{"reason":"Indirectly required by django.contrib.postgres for PostgreSQL database features if not using other psycopg2 drivers","package":"psycopg2-binary","optional":true}],"imports":[{"symbol":"Index","correct":"from modelsearch.base import Index"},{"symbol":"SearchField","correct":"from modelsearch.fields import SearchField"},{"symbol":"MatchAll","correct":"from modelsearch.query import MatchAll"},{"note":"Backend classes are nested within submodules like `modelsearch.backends.elasticsearch` or `modelsearch.backends.database`","wrong":"from modelsearch.backends import ElasticsearchSearchBackend","symbol":"ElasticsearchSearchBackend","correct":"from modelsearch.backends.elasticsearch import ElasticsearchSearchBackend"}],"quickstart":{"code":"import os\nfrom django.db import models\nfrom modelsearch.base import Index\nfrom modelsearch.fields import SearchField\nfrom modelsearch.query import MatchAll\nfrom django.conf import settings\n\n# Minimal Django settings setup for quickstart, typically in settings.py\nif not settings.configured:\n    settings.configure(\n        INSTALLED_APPS=[\n            \"modelsearch\",\n            \"django.contrib.postgres\" # For PostgreSQL DB search features\n        ],\n        MODELSEARCH_BACKENDS={\n            \"default\": {\n                \"BACKEND\": \"modelsearch.backends.database.DatabaseSearchBackend\"\n                # \"BACKEND\": \"modelsearch.backends.elasticsearch.ElasticsearchSearchBackend\",\n                # \"URLS\": [os.environ.get('ELASTICSEARCH_URL', 'http://localhost:9200')],\n                # \"INDEX\": \"test_modelsearch\",\n            }\n        },\n        DATABASES={\n            \"default\": {\n                \"ENGINE\": \"django.db.backends.sqlite3\",\n                \"NAME\": \":memory:\",\n            }\n        },\n        SECRET_KEY=\"dummy-secret-key\"\n    )\n\n# Define a Django Model\nclass Article(models.Model):\n    title = models.CharField(max_length=255)\n    body = models.TextField()\n\n    class Search(Index):\n        fields = [\n            SearchField(\"title\", boost=10),\n            SearchField(\"body\"),\n        ]\n\n    def __str__(self):\n        return self.title\n\n# Example usage (run after Django setup and migrations)\n# This part assumes a database is configured and tables are created.\n# For a real application, you'd run `manage.py migrate` and then `manage.py update_index`.\nif __name__ == \"__main__\":\n    # In a real Django project, you'd import Article and use its manager.\n    # For this isolated example, we simulate object creation.\n    # Note: Search index update requires running `manage.py update_index` or calling backend manually.\n    print(\"Quickstart will only demonstrate search query structure.\")\n    print(\"To run fully, ensure Django is setup, migrated, and index updated.\")\n\n    # Example search (using a dummy queryset for demonstration)\n    # In a real app, this would be: `Article.objects.search(\"search term\")`\n    search_query = \"example\"\n    # Simulate a search call\n    class MockSearchManager:\n        def search(self, query):\n            print(f\"Searching for: {query}\")\n            return [\"MockResult1\", \"MockResult2\"]\n\n    mock_manager = MockSearchManager()\n\n    print(f\"\\nSearch for '{search_query}':\")\n    results = mock_manager.search(search_query)\n    print(f\"Results: {results}\")\n\n    print(\"\\nSearch for all with MatchAll():\")\n    results_all = mock_manager.search(MatchAll())\n    print(f\"Results: {results_all}\")","lang":"python","description":"Define a Django model with an inner `Search` class that specifies fields to index. Configure `MODELSEARCH_BACKENDS` in your Django settings. Use the `search()` method on your model's manager to query the index. Remember to run `manage.py update_index` after defining models or changing their data to populate the search index."},"warnings":[{"fix":"Upgrade your OpenSearch cluster to version 2.x or later, or downgrade `django-modelsearch` to a version prior to 1.1 if upgrading OpenSearch is not an option.","message":"Support for OpenSearch 1.x was dropped in version 1.1, which aligns with OpenSearch's End-of-Life for that series. Users on OpenSearch 1.x must upgrade their OpenSearch cluster or use an older version of django-modelsearch (pre-1.1).","severity":"breaking","affected_versions":">=1.1"},{"fix":"Carefully review your `MODELSEARCH_BACKENDS` settings and model `Search` class definitions. Re-indexing your data after upgrading is highly recommended (`python manage.py update_index`).","message":"Version 1.0 was a fork from Wagtail's internal search module. If you are migrating from an older Wagtail project that used its built-in search before this fork, direct migration might require adjustments to settings and index definitions, as some internal paths or configurations may have changed.","severity":"breaking","affected_versions":">=1.0"},{"fix":"Remove the `_WAGTAILSEARCH_FORCE_AUTO_UPDATE` setting from your configuration. If its functionality was critical, you may need to implement similar logic manually or adjust your indexing strategy.","message":"The hidden setting `_WAGTAILSEARCH_FORCE_AUTO_UPDATE` was removed in version 1.1.1. While not a public API, any reliance on this internal setting will cease to function.","severity":"deprecated","affected_versions":">=1.1.1"},{"fix":"Add `'django.contrib.postgres'` to your `INSTALLED_APPS` list in `settings.py`.","message":"For PostgreSQL database search and certain ORM features (like `SearchVector`), you must include `django.contrib.postgres` in your `INSTALLED_APPS`.","severity":"gotcha","affected_versions":"all"},{"fix":"Thoroughly review the `MODELSEARCH_BACKENDS` documentation for your chosen backend (Elasticsearch, OpenSearch, or Database). Ensure URLs are correct, indices exist (or are created), and permissions are set up correctly for your backend service.","message":"Configuring search backends (`MODELSEARCH_BACKENDS`) correctly is crucial. Misconfigurations can lead to indexing failures or incorrect search results without immediate errors. Pay close attention to backend types, URLs, and index names.","severity":"gotcha","affected_versions":"all"}],"env_vars":null,"last_verified":"2026-04-09T00:00:00.000Z","next_check":"2026-07-08T00:00:00.000Z"}