Rejuvenating vs deprecating Form.Media

I worry that we’re trying to do too much here. Writing the DEP requires a lot of time and energy, and then the implementation and testing and consensus reaching hasn’t even happened yet.

What if we switched to just introducing the JS() object from django-js-asset into Django and changed some of the code in Django itself to take advantage of it?

One small example where having JS() would have allowed us to keep a template smaller would be here:

This could have been a JS("admin/js/change_form.js", {"data-model-name": self.model._meta.model_name}) block somewhere in the model admin or model form declaration. (As an aside, the ID could be replaced by using document.currentScript.)

The same applies to the popup response, to the prepopulated fields snippet and so on.

we’re going to deprecate Form.Media.

I really hope that won’t be a result of this process :slight_smile:

Bare scripts and CSS files without bundlers are still useful, or maybe even more useful than they were a few years ago – with htmx and all the great advances made with CSS, JavaScript and vanilla browser APIs.

I’d love to see that added to Django :slight_smile: From my side I’m still interested in researching this more, but I do think the JS object would go a long way in a backwards-compatible way.

From my side – main reason to move slow on the DEP has been browser support for the specific browser APIs I’d like to consider for inclusion in Media, namely import maps and declarative shadow DOM. This is all good now in October 2024 though so I’m planning to get back to this soon™.

Edit: For extra visibility, here are the relevant Wagtail issues that I want to get to before this DEP, both scheduled for me to work on in October - November:


Re deprecation – through this thread we’ve identified active usage of Media in django CMS, Wagtail, feincms3, Mezzanine. And interest from a few of us in modernizing the Media API. Feels like there’s a clear need here, though I suppose the API can clearly be more elegant.

2 Likes

Hi! I’m catching up on this conversation. Can I point you to the thread I opened about integrating importmaps and the project I started to implement this idea?

The main idea behind dj-importmap is to declare importmaps in a Django project in a way that IDEs can comprehend to propose autocolpletion in JS files if that becomes the Django standard. dj-importmap relies on a importmaps.py similar to how urls.py works (from a user perspective). I started to use it on a project for a client and I’d love to see the community get behind it, expand it with features and adopt it (or another) as the standard.

Also, related to this, I’d really love a mechanism for templates to declare assets so the view can collect them and include them only once, quite similar to what Media proposes for Form. It is not rare to me to get in the situation where I’d like to {% include %} a partial — potentially more than once — in a template but that partial requires some JS code to be useful. In that situation, the only solution I have is to leave a comment on the template to indicate that these assets also need to be included in the template, which is not conform to the modern practice of declaring self-sufficient components.

I don’t know how complex it is to develop, but I imagine an {% asset %} tag that would do for templates what Media does for form. That tag would be treated differently to other tag and processed at the very end of rendering so that all assets declared by all partials are collected and made available for inclusion in the HTML.

1 Like

Hi hristophehenry,

I’d love to combine forces on this. I wrote Django-ESM a while ago, and we are using it in a company backed production environment.

If you’re interested, please don’t hesitate to ask.

I will probably also address the topic at the next Berlin Django meetup, to gather more ideas from the community.

Cheers!
Joe

Regarding quick wins:

Django’s test suite includes a great example of how to include ES modules in Form.media.js, but it’s only not part of the public API.

It would be a nice start to have a documented way on how to add a <script type="module"> to form media. This is particularly great, if you use web component based custom inputs (Widgets).

I usually use a subclass in my code bases:

class ESM(Asset):
    """A JavaScript asset for ECMA Script Modules (ESM)."""

    def __str__(self):
        path = super().__str__()
        template = '<script src="{}" type="module"></script>'
        return format_html(template, self.absolute_path(path))

Followed by:

class Form:
    class Media:
        js = [ESM("path/to/file.jsm")]

This works nicely, but once could also build a more generic Script asset, that accepts keyword arguments, like so:

class Form:
    class Media:
        js = [Script(src="path/to/file.jsm", type="module")]

That’s already tested and supported by Django and is only missing great documentation.

Small quick win?

Cheers,
Joe

2 Likes

Very much in favour of any small quick win here! The only thing I’d also like to see (and that doesn’t strike me as too big to maybe smuggle in with this) is to support other attributes aswell. The main reason that I’m not using form.media (well, apart from using django-compressor extensively) is that I load >99% of my scripts with <script defer> or <script async>, and I think we should encourage this / make it easy in general.

It should be easy enough (famous last words). But since custom assets have been supported for a couple of Versions now, it probably fine to squeeze it into the LTS before the feature freeze. I’ll draft a ticket.

1 Like

#35886 (Move object-based media assets to the public API) – Django and here it is.

2 Likes

Thanks! I think there’s value in not just supporting standard attributes but also arbitrary data-* attributes, so that additional data can be attached to document.currentScript. I think that’s missing from #35886 currently. Apart from that it’s a good start I think. (Sorry for the silence from my side, I haven’t yet found the time to react to the DEP comments.)

Ok, then, I took some time to properly implement object-based assets as part of the public API:

I tried to keep the scope as narrow as possible, to move this along quickly. I’d love a review, if someone finds the time.

Thanks :pray:

1 Like