django-admin-site-search
A global/site search modal for the Django admin.
Features
- 🎩 Works out-of-the-box, with minimal config.
- 🔎 Search performed on:
- App labels.
- Model labels and field attributes.
- Model instances, with two options for a search method:
model_char_fields(default): AllCharField(and subclass) values, with__icontains.admin_search_fields: Invoke each ModelAdmin's get_search_results(...) method.
- 🔒 Built-in auth: users can only search apps and models that they have permission to view.
- ⚡ Results appear on-type, with throttling/debouncing to avoid excessive requests.
- 🎹 Keyboard navigation (cmd+k, up/down, enter).
- ✨ Responsive, and supports dark/light mode.
- Django's built-in CSS vars are used to match your admin theme.
Requirements
- Python 3.7 - 3.12.
- Django 3.2 - 5.1.
Setup
1. Install
- Install with your package manager, e.g.
pip install django-admin-site-search. - Add
admin_site_searchto yourINSTALLED_APPSsetting.
2. Add View
- If you haven't already, override/extend the default AdminSite.
- Add the
AdminSiteSearchViewto your AdminSite:
from django.contrib import admin
from admin_site_search.views import AdminSiteSearchView
class MyAdminSite(AdminSiteSearchView, admin.AdminSite):
...
3. Add Templates
- If you haven't already, create
admin/base_site.htmlin yourtemplates/directory.- Note: if your
templates/directory is inside of an app, then that app must appear inINSTALLED_APPSbefore your custom admin app.
- Note: if your
- Include the
admin_site_searchtemplates:
{% extends "admin/base_site.html" %}
{% block extrahead %}
{% include 'admin_site_search/head.html' %}
{{ block.super }}
{% endblock %}
{% block footer %}
{{ block.super }}
{% include 'admin_site_search/modal.html' %}
{% endblock %}
{% block usertools %}
{% include 'admin_site_search/button.html' %}
{{ block.super }}
{% endblock %}
Notes
- Along with styles,
admin_site_search/head.htmlloads Alpine JS.- This is bundled into
/static/, to avoid external dependencies.
- This is bundled into
- The placement of
modal.htmlandbutton.htmlare not strict, though the former would ideally be in a top-level position.- Django 4.x exposes
{% block header %}- this is preferable tofooter.
- Django 4.x exposes
Customisation
Class attributes
class MyAdminSite(AdminSiteSearchView, admin.AdminSite):
# Sets the last part of the search route (`<admin_path>/search/`).
site_search_path: str = "search/"
# Set the search method/behaviour.
site_search_method: Literal["model_char_fields", "admin_search_fields"] = "model_char_fields"
Methods
def match_app(
self, request, query: str, name: str
) -> bool:
"""DEFAULT: case-insensitive match the app name"""
def match_model(
self, request, query: str, name: str, object_name: str, fields: List[Field]
) -> bool:
"""DEFAULT: case-insensitive match the model and field attributes"""
def match_objects(
self, request, query: str, model_class: Model, model_fields: List[Field]
) -> QuerySet:
"""DEFAULT: Returns the QuerySet after performing an OR filter across all Char fields in the model."""
def filter_field(
self, request, query: str, field: Field
) -> Optional[Q]:
"""DEFAULT: Returns a Q 'icontains' filter for Char fields, otherwise None
Note: this method is only invoked if model_char_fields is the site_search_method."""
def get_model_queryset(
self, request, model_class: Model, model_admin: Optional[ModelAdmin]
) -> QuerySet:
"""DEFAULT: Returns the model class' .objects.all() queryset."""
def get_model_class(
self, request, app_label: str, model_dict: dict
) -> Optional[Model]:
"""DEFAULT: Retrieve the model class from the dict created by admin.AdminSite"""
Example
Add TextField results to search.
from django.contrib import admin
from django.db.models import Q, Field, TextField
from admin_site_search.views import AdminSiteSearchView
class MyAdminSite(AdminSiteSearchView, admin.AdminSite):
site_search_method: "model_char_fields"
def filter_field(self, request, query: str, field: Field) -> Optional[Q]:
"""Extends super() to add TextField support to site search"""
if isinstance(field, TextField):
return Q(**{f"{field.name}__icontains": query})
return super().filter_field(query, field)
Note that this isn't done by default for performance reasons: __icontains on a
large number of text entries is suboptimal.
Screenshots
Release files for django-admin-site-search 1.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| django_admin_site_search-1.1.0.tar.gz | 35.3 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| django_admin_site_search-1.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 71.6 kB
Release files / django_admin_site_search-1.1.0.tar.gz
| Download URL | django_admin_site_search-1.1.0.tar.gz |
|---|---|
| Size | 35.3 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
86bd0c2a132ae0db353c29eb3eebe9ca92e9208db09f43ee99b30aaba03a4cf4
|
|
BLAKE2b-256 checksum How to use checksums |
ee6c3c9a7e3c63e6dd5ed645ec499899c39d4914627f2e8638e295cbb89a0aa3
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.12.7
|
Release files / django_admin_site_search-1.1.0-py3-none-any.whl
| Download URL | django_admin_site_search-1.1.0-py3-none-any.whl |
|---|---|
| Size | 36.3 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
fee2318007f87ca2e996d10ead82aa11bdb1858caa7aa23758a164bcc2b0eab3
|
|
BLAKE2b-256 checksum How to use checksums |
9df26ab1d366e52b250210056656022fb329c94fb1aa3457b80a1f32eb47d1f1
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/5.1.1 CPython/3.12.7
|