diff --git a/django/contrib/admin/options.py b/django/contrib/admin/options.py index 8ffc460177..f466614061 100644 --- a/django/contrib/admin/options.py +++ b/django/contrib/admin/options.py @@ -559,6 +559,7 @@ class ModelAdmin(BaseModelAdmin): list_max_show_all = 200 list_editable = () search_fields = () + search_help_text = None date_hierarchy = None save_as = False save_as_continue = True @@ -747,6 +748,7 @@ class ModelAdmin(BaseModelAdmin): self.list_editable, self, sortable_by, + self.search_help_text, ) def get_object(self, request, object_id, from_field=None): diff --git a/django/contrib/admin/static/admin/css/changelists.css b/django/contrib/admin/static/admin/css/changelists.css index b4a1557887..a4baf32955 100644 --- a/django/contrib/admin/static/admin/css/changelists.css +++ b/django/contrib/admin/static/admin/css/changelists.css @@ -125,6 +125,10 @@ margin-right: 4px; } +#changelist-search .help { + word-break: break-word; +} + /* FILTER COLUMN */ #changelist-filter { diff --git a/django/contrib/admin/templates/admin/search_form.html b/django/contrib/admin/templates/admin/search_form.html index 75c629cd62..fd7818a9f8 100644 --- a/django/contrib/admin/templates/admin/search_form.html +++ b/django/contrib/admin/templates/admin/search_form.html @@ -12,5 +12,9 @@ {% if pair.0 != search_var %}{% endif %} {% endfor %} +{% if cl.search_help_text %} +
+
{{ cl.search_help_text }}
+{% endif %} {% endif %} diff --git a/django/contrib/admin/views/main.py b/django/contrib/admin/views/main.py index e446cc716e..9ac557ea71 100644 --- a/django/contrib/admin/views/main.py +++ b/django/contrib/admin/views/main.py @@ -49,7 +49,8 @@ class ChangeList: def __init__(self, request, model, list_display, list_display_links, list_filter, date_hierarchy, search_fields, list_select_related, - list_per_page, list_max_show_all, list_editable, model_admin, sortable_by): + list_per_page, list_max_show_all, list_editable, model_admin, sortable_by, + search_help_text): self.model = model self.opts = model._meta self.lookup_opts = self.opts @@ -68,6 +69,7 @@ class ChangeList: self.model_admin = model_admin self.preserved_filters = model_admin.get_preserved_filters(request) self.sortable_by = sortable_by + self.search_help_text = search_help_text # Get search parameters from the query string. _search_form = self.search_form_class(request.GET) diff --git a/docs/ref/contrib/admin/index.txt b/docs/ref/contrib/admin/index.txt index f1c64bea28..99d6d2dcc8 100644 --- a/docs/ref/contrib/admin/index.txt +++ b/docs/ref/contrib/admin/index.txt @@ -1381,6 +1381,13 @@ subclass:: Support for searching against quoted phrases with spaces was added. +.. attribute:: ModelAdmin.search_help_text + + .. versionadded:: 4.0 + + Set ``search_help_text`` to specify a descriptive text for the search box + which will be displayed below it. + .. attribute:: ModelAdmin.show_full_result_count Set ``show_full_result_count`` to control whether the full count of objects diff --git a/docs/releases/4.0.txt b/docs/releases/4.0.txt index 761b47b982..54de681a81 100644 --- a/docs/releases/4.0.txt +++ b/docs/releases/4.0.txt @@ -75,6 +75,9 @@ Minor features * The new context variable ``model`` which contains the model class for each model is added to the :meth:`.AdminSite.each_context` method. +* The new :attr:`.ModelAdmin.search_help_text` attribute allows specifying a + descriptive text for the search box. + :mod:`django.contrib.admindocs` ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/tests/admin_changelist/tests.py b/tests/admin_changelist/tests.py index c5910d6bdb..0b8535beb7 100644 --- a/tests/admin_changelist/tests.py +++ b/tests/admin_changelist/tests.py @@ -1328,6 +1328,22 @@ class ChangeListTests(TestCase): # The "Add" button inside the object-tools shouldn't appear. self.assertNotIn('Add ', response.rendered_content) + def test_search_help_text(self): + superuser = self._create_superuser('superuser') + m = BandAdmin(Band, custom_site) + # search_fields without search_help_text. + m.search_fields = ['name'] + request = self._mocked_authenticated_request('/band/', superuser) + response = m.changelist_view(request) + self.assertIsNone(response.context_data['cl'].search_help_text) + self.assertNotContains(response, '
') + # search_fields with search_help_text. + m.search_help_text = 'Search help text' + request = self._mocked_authenticated_request('/band/', superuser) + response = m.changelist_view(request) + self.assertEqual(response.context_data['cl'].search_help_text, 'Search help text') + self.assertContains(response, '
Search help text
') + class GetAdminLogTests(TestCase):