A search (cmd+k) modal, for the Django admin UI, that searches your entire site.
Project description
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_search
to yourINSTALLED_APPS
setting.
2. Add View
- If you haven't already, override/extend the default AdminSite.
- Add the
AdminSiteSearchView
to 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.html
in yourtemplates/
directory.- Note: if your
templates/
directory is inside of an app, then that app must appear inINSTALLED_APPS
before your custom admin app.
- Note: if your
- Include the
admin_site_search
templates:
{% 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.html
loads Alpine JS.- This is bundled into
/static/
, to avoid external dependencies.
- This is bundled into
- The placement of
modal.html
andbutton.html
are 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
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file django_admin_site_search-1.1.0.tar.gz
.
File metadata
- Download URL: django_admin_site_search-1.1.0.tar.gz
- Upload date:
- Size: 35.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 86bd0c2a132ae0db353c29eb3eebe9ca92e9208db09f43ee99b30aaba03a4cf4 |
|
MD5 | a1f61c08b4e2203051c763b7512bf9e3 |
|
BLAKE2b-256 | ee6c3c9a7e3c63e6dd5ed645ec499899c39d4914627f2e8638e295cbb89a0aa3 |
File details
Details for the file django_admin_site_search-1.1.0-py3-none-any.whl
.
File metadata
- Download URL: django_admin_site_search-1.1.0-py3-none-any.whl
- Upload date:
- Size: 36.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/5.1.1 CPython/3.12.7
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | fee2318007f87ca2e996d10ead82aa11bdb1858caa7aa23758a164bcc2b0eab3 |
|
MD5 | f473bfe5f8d3ffd5f99ba1219e7dee56 |
|
BLAKE2b-256 | 9df26ab1d366e52b250210056656022fb329c94fb1aa3457b80a1f32eb47d1f1 |