22

I have a heavily customized Django admin where it's very simple to load a custom JS file for each of my ModelAdmins:

class MyModelAdmin(admin.ModelAdmin):
    class Media:
        js = ('js/admin/mymodel.js',)

But how do I do this for the admin "homepage," where all my admin models are listed?

Update #1: amending my question, since the solutions below aren't that useful if I cannot efficiently include Django's jQuery. So, how do I include Django's jQuery in the JS file? If I wrap my code with (as I do in my other ModelAdmin JS files):

(function ($) {
    // my code here...
})(django.jQuery);

I get the following error:

ReferenceError: django is not defined.

Thanks.

Update #2: I was able to include Django's jQuery successfully by following this answer: https://stackoverflow.com/a/10584539/585783

Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129
Cloud Artisans
  • 4,016
  • 3
  • 30
  • 37

2 Answers2

33

You can override templates/admin/index.html and add the JavaScript in the block extrahead:

{% extends "admin/index.html" %}

{% block extrahead %}
    {{ block.super }}
    # add a <script> tag here with your JavaScript
{% endblock %}
guettli
  • 25,042
  • 81
  • 346
  • 663
Simeon Visser
  • 118,920
  • 18
  • 185
  • 180
  • This works and seems clean, thanks... However, how do I include jQuery in the JS file? If I wrap my code with `(function ($) { ... })(django.jQuery);` the same as in my other ModelAdmin JS files, I get a "ReferenceError: django is not defined" – Cloud Artisans Nov 11 '13 at 19:45
  • jQuery is pre-bundled in the Django admin - you don't need to add it in manually. – shacker Apr 20 '17 at 22:32
  • 6
    The above solution will overwrite all code contained in the extrahead block, which might be the reason for the "ReferenceError: django is not defined" error. If you add a `{{ block.super }}` inside the `{% block extrahead %} ... {% endblock %}` existing code is preserved. – tobltobs Jun 05 '17 at 15:45
  • 1
    @tobltobs I updated the answer. Does it look correct now? – guettli Mar 03 '20 at 11:56
  • 3
    It doesn't work. Adding template to `templates/admin/index.html` doesn't change anything. – EugZol Jan 11 '21 at 12:25
  • @EugZol having the same problem, did this change? – MikeSchem May 30 '22 at 04:12
  • 1
    @MikeSchem That was a long time ago and I don't remember what I did next. Currently I see `./template/admin//base_site.html`. First line of that file is `{% extends "admin/base_site.html" %}`. `` is a name of subfolder in the project, where I put all admin models. Hope that helps. – EugZol May 31 '22 at 13:00
1

You can load custom js files only on Home admin page. *My answer explains how to load CSS and JavaScript files in Django.

For example, set BASE_DIR / 'templates' to DIRS in TEMPLATES and set BASE_DIR / 'static/' to STATICFILES_DIRS in settings.py as shown below so that Django can recognize templates and static folders just under django-project. *My answer explains how to set Django Templates and I recommand to set whitenoise following my answer to disable your browser to cache the static files of Django: in settings.py as shown below:

# "core/settings.py"

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [
            BASE_DIR / 'templates' # Here
        ],
        ...
    },
]

...

STATIC_URL = 'static/'
STATICFILES_DIRS = [
    BASE_DIR / 'static/' # Here
]

Then, create custom.js in static/admin/js/ and copy index.html from django/contrib/admin/static/admin/index.html in your virtual environment to templates/admin/ as shown below:

django-project
 |-core
 |  └-settings.py
 |-app1
 |-app2
 |-static
 |  └-admin
 |     └-js
 |        └-custom.js # Here
 └-templates
    └-admin
       └-index.html # Here

Then, set alert("Hello World"); to custom.js as shown below:

# "static/admin/js/custom.js"

alert("Hello World");

Then, set custom.js after {% block sidebar %} in index.html as shown below:

# "templates/admin/index.html"

# ...
{% block sidebar %}
{# ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ Here ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ #}
<script src="{% static 'admin/js/custom.js' %}" defer></script>
{# ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ Here ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ #}
<div id="content-related">
# ...

Now, Hello World is shown only on Home admin page as shown below:

enter image description here

In addition, you can load custom.js on all admin pages.

So, copy base.html from django/contrib/admin/static/admin/base.html in your virtual environment to templates/admin/ as shown below:

django-project
 |-core
 |  └-settings.py
 |-app1
 |-app2
 |-static
 |  └-admin
 |     └-js
 |        └-custom.js
 └-templates
    └-admin
       └-base.html # Here

Then, set custom.js after <link ... "admin/css/base.css" %}{% endblock %}"> in base.html as shown below, then Hello World is shown on all admin pages:

# "templates/admin/base.html"

# ...
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="{% block stylesheet %}{% static "admin/css/base.css" %}{% endblock %}">
{# ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ Here ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ #}
<script src="{% static 'admin/js/custom.js' %}" defer></script>
{# ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ Here ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ #}
{% block dark-mode-vars %}
  <link rel="stylesheet" href="{% static "admin/css/dark_mode.css" %}">
# ...

Be careful, django/contrib/admin/static/admin/js/ has the js files for Django Admin so you should not use the same file names in it to add custom js files to Django Admin as long as you need to overwrite them.

And, running the code below can gether all static files in Django Project into static folder without deleting custom and overwritten js files.

python manage.py collectstatic
Super Kai - Kazuya Ito
  • 22,221
  • 10
  • 124
  • 129