Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I change the search field label in Django admin?

Tags:

django

In Django admin.py

class TableAdmin(admin.ModelAdmin):
    search_fields = ["name", "description", "category"]
    list_display = ["name", "description", "category"]

admin.site.register(Table, TableAdmin)

Here, we can change the list_display, label name by using below code,

name.short_description = "Product Name"

Now the question is, How do I change the search fields label name?

like image 367
FeLiX StEpHeN Avatar asked Sep 12 '25 01:09

FeLiX StEpHeN


2 Answers

You can override django admin template's search_form.html file.

create a new html file similar to it, and name it search_form.html:

{% load i18n static %}
{% if cl.search_fields %}
<div id="toolbar"><form id="changelist-search" method="get">
<div><!-- DIV needed for valid HTML -->
<label for="searchbar"><img src="{% static "admin/img/search.svg" %}" alt="Search" /></label>
<input type="text" size="40" name="{{ search_var }}" value="{{ cl.query }}" id="searchbar" autofocus />
<input type="submit" value="{% trans 'My Search' %}" />
{% if show_result_count %}
    <span class="small quiet">{% blocktrans count counter=cl.result_count %}{{ counter }} result{% plural %}{{ counter }} results{% endblocktrans %} (<a href="?{% if cl.is_popup %}_popup=1{% endif %}">{% if cl.show_full_result_count %}{% blocktrans with full_result_count=cl.full_result_count %}{{ full_result_count }} total{% endblocktrans %}{% else %}{% trans "Show all" %}{% endif %}</a>)</span>
{% endif %}
{% for pair in cl.params.items %}
    {% if pair.0 != search_var %}<input type="hidden" name="{{ pair.0 }}" value="{{ pair.1 }}"/>{% endif %}
{% endfor %}
</div>
</form></div>
{%endif %}

Then put it in your template directory's admin folder like: (template directory)>admin>search_form.html

And it should override the label of search button with text 'My Search'

like image 118
ruddra Avatar answered Sep 13 '25 16:09

ruddra


Is it possible to override it just for specific admin model(s)? Yes this is possible.

In order to do so you need to create following files.

YourApp
   -> templatetags
          -> __init__.py
          -> custom_tags.py
   -> admin_overrides
          -> InclusionAdminNode

Now you have to register a custom tag) which renders the Search Form.

from django.contrib.admin.views.main import (
    SEARCH_VAR,
)
from django.template import Library

from ..admin_overrides.InclusionAdminNode import InclusionAdminNode

register = Library()


def search_form(cl):
    """
    Display a search form for searching the list.
    """
    return {
        'cl': cl,
        'show_result_count': cl.result_count != cl.full_result_count,
        'search_var': SEARCH_VAR
    }


@register.tag(name='search_custom_form')
def search_form_tag(parser, token):
    return InclusionAdminNode(parser, token, func=search_form, template_name='custom_search_form.html',
                              takes_context=False)

Now, we have to use this tag in our YourApp/change_list.html.

    {% block search %}{% search_custom_form cl %}{% endblock %}

Note: Now still you will see that there is no change in the form. But here is the catch we have to add our custom InclusionAdminNode and change the template path. By default it pick from admin.

from inspect import getfullargspec

from django.template.library import InclusionNode, parse_bits


class InclusionAdminNode(InclusionNode):
    """
    Template tag that allows its template to be overridden per model, per app,
    or globally.
    """

    def __init__(self, parser, token, func, template_name, takes_context=True):
        self.template_name = template_name
        params, varargs, varkw, defaults, kwonly, kwonly_defaults, _ = getfullargspec(func)
        bits = token.split_contents()
        args, kwargs = parse_bits(
            parser, bits[1:], params, varargs, varkw, defaults, kwonly,
            kwonly_defaults, takes_context, bits[0],
        )
        super().__init__(func, takes_context, args, kwargs, filename=None)

    def render(self, context):
        opts = context['opts']
        app_label = opts.app_label.lower()
        object_name = opts.object_name.lower()
        # Load template for this render call. (Setting self.filename isn't
        # thread-safe.)
        context.render_context[self] = context.template.engine.select_template([
            'YourApp/%s/%s/%s' % (app_label, object_name, self.template_name),
            'YourApp/%s/%s' % (app_label, self.template_name),
            'YourApp/%s' % (self.template_name,),
        ])
        return super().render(context)

That's it we are good to go now.

Hope this is helpful.

like image 40
Nitish Kumar Avatar answered Sep 13 '25 16:09

Nitish Kumar