How to add script type="module" in django admin

Question:

If I want some javascript functionality in my Django admin, I usually go about it using the Media class like this:

@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):

    class Media:
        js = ('js/my_script.js',)

But I now have a script that is a ES6 module so I would like Django to render it like:

<script src="path/to/static/js/my_script" type="module"></script>

and using the Media class doesn’t render the type="module" attribute.

Any help or tips to achieve this? Thanks

Asked By: damores

||

Answers:

In your custom change_form.html template, extend the admin_change_form_document_ready block and add the event listener code

{% extends 'admin/change_form.html' %}
{% load static %}

{% block admin_change_form_document_ready %}
{{ block.super }}
<script type="text/javascript" src="{% static 'app/your_file.js' %}"></script>
{% endblock %}
Answered By: rahul.m

You won’t be able to use Media class for this, if you check at the code, the method will always render the same type="text/javascript".

If you really want to go with the Media way, you could create your own Mediaclass and inherit from forms.Media, then you could try using Media as a dynamic property that would be able to generate a script with type="module".

Another option is to use a custom template as suggested before, or even considering adding a templatetag to your app in order to add ES6 modules in your template.

Answered By: menecio
@admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):

    class Media:
        module = ('js/my_script.js',)

You can just change js to replace module its define is type of src

It‘s working for me.

Answered By: KANAIYALAL CHENVA

We can overwrite the Media.render_js to add anything we want to add to tag.

from django.forms.widgets import Media

def render_js(self) -> List[str]:
    script_js = []

    for path in self._js:
        module_mark = ""

        # Put your own condition here, in my case it generates
        # <script type="module" src="http://localhost:5173/@vite/client"></script>
        # and <script type="module" src="http://localhost:5173/src/custom_admin.ts"></script>
        # into head scripts
        if isinstance(path, str) and (
            "custom_admin" in path or "@vite/client" in path
        ):
            module_mark = ' type="module"'

        js = format_html(
            '<script%s src="{}"></script>' % module_mark,
            self.absolute_path(path),
        )

        script_js.append(js)

    return script_js


Media.render_js = render_js

class MyModelAdmin(admin.ModelAdmin):
    class Media:
        js = (
            "http://localhost:5173/@vite/client",
            "http://localhost:5173/src/custom_admin.ts",
        )

Just adjust above code to adapt your logic and add it to your admin.py.

Answered By: Vincent Wen
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.