Thanks David for investigating the topic thoroughly! I wasn't expecting all that when I filed a one-line ticket six years ago :-) So, here's a bunch of opinions.
Rendering an attractive and easy-to-use Web form requires more than just
HTML - it also requires CSS stylesheets, and if you want to use fancy
« Web2.0 » widgets, you may also need to include some JavaScript on each
page. The exact combination of CSS and JavaScript that is required for
any given page will depend upon the widgets that are in use on that page.
That was the reasonable thing to do before single-page apps, asset pipelines, bundlers and code splitting. It's still a fairly reasonable thing to do on a website that relies on good old HTML forms but would benefit from "fancy « Web2.0 » widgets".
1. Django shouldn't do anything (besides what django.contrib.staticfiles already does) for projects that use webpack (or any other bundler)
The correct approach with a bundler is to bundle all JavaScript code and, if needed, to optimize with code splitting. Attempting to include only what's needed on each page, like Media does, will usually be counterproductive, because it will general different bundle for different pages and defeat caching by the browser.
Then I know two techniques for integrating the frontend code with Django:
- the
single page app (website and API on separate domains) — this is clearly out of scope of this discussion as Django only provides an API in this scenario
- what I call the
hybrid app (website and API on the same domain) — here django.contrib.staticfiles helps; it comes after the JavaScript bundler in the deployment pipeline (and I prefer plain django.contrib.staticfiles over django-webpack-loader, but that's another story)
(NB: while the blog posts I just linked to focus on create-react-app, the concepts apply to any modern JavaScript toolchain.)
Regardless, Django already provides more than we need. For example, both webpack and django.contrib.staticfiles add hashes to file names to ensure cache invalidation.
So my answer to questions 3, 4 and 5 is "no, except maybe documentation".
Now, let's leave this brave new world and remember the jQuery era.
2. Media makes sense
Although pluggable apps are fantastic, the concept doesn't work well for templates, which is where <link rel="stylesheet"> and <script> tags are written. As a consequence, there's no good way for a pluggable app to add CSS and JS for rendering a rich field, that is, a better <input>.
Pluggable apps could provide custom template tags for rich fields — it's fairly easy with
inclusion_tag — but that would require writing a specific template for each form. That wouldn't support rendering all fields in a loop like the admin does. This is where Form Media fills the gap.
Form Media is a data structure representing a list of <link rel="stylesheet"> tags and a list of <script> tags, nothing more, nothing less. It knows how to render itself to HTML. When merging two instances (or extending one), it deduplicates tags while maintaining their order.
Form Media is the only place where Django renders <link> or <script> tags in Python. Everywhere else, these tags are written in Django templates. This is consistent with my observation that Django templates don't provide a convenient solution for pluggable rich fields.
For websites that haven't adopted a site-wide asset pipeline, this is useful, self-contained, well-defined functionality. It doesn't have to fit into a bigger design.
3. Areas for improvement
The name is wrong — it should be Static — which is why I originally filed the ticket. This is a backwards-incompatible change. I haven't thought about how a deprecation path could work.
The docs describe a fallback to MEDIA_URL which, as far as I can tell, no longer exists. This paragraph should be removed.
The API would be simpler if `css` was a list rather than a dict of lists keyed by media. Media-specific styles could be written inside a media query. Accepting lists in addition to the more verbose, dict-based format would be convenient and backwards-compatible.
4. Could Django do more?
I don't believe Django should have the ability to compile and compress assets. It's a messy problem; we don't have the resources to tackle it. I'd rather leave it to third-party apps like we currently do.
To me, the key question is — is there something useful that Django can do beyond what it currently does, short of providing an asset pipeline?
The discussion often revolves about listing which assets to include in a page:
- Media is basically a list of assets
- Claude's work was about letting apps describe a list of assets
- django-compressor extracts lists of assets by parsing HTML inside {% compress %} tags, if memory serves
- django-pipeline asks the user to include a list of assets in a setting
Perhaps Django could standardize a way to accumulate a list of CSS and JS assets to include in a page, which could then be rendered in HTML, perhaps after optimizations (provided by third party apps).
Essentially this would solve the same problem as django-sekizai and could provide a better integration point for django-compressor.
To move forwards, we'd need a better description of the problem to be solved and of the expected benefits of the proposed solution. This sounds a lot like a DEP ;-)
If we did that, we'd still need the Media (or Static) class on forms, except it would feed its data into this new system instead of rendering HTML. Since it's here to stay, we should proceed with the renaming.
I hope this helps!