Opened 3 years ago

Closed 3 years ago

Last modified 3 years ago

#28377 closed Cleanup/optimization (fixed)

Retain order of form media assets during aggregation

Reported by: Johannes Hoppe Owned by: info@…
Component: Forms Version: 1.11
Severity: Normal Keywords:
Cc: Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

The order of static asset can matter, be it JavaScript code, that depends on jQuery or CSS files, that overwrite each other.
Currently Django does not retain the order specified in the Media property. When merging to Media objects, like widget and form media, unique entries only get amended which can change the order of assets.

Example:

>>> from django.forms import Media
>>> m1 = Media(js=('jQuery.js', 'script.js', 'noConflict.js'))
>>> m2 = Media(js=('jQuery.js', 'yet_another_script.js', 'noConflict.js'))
>>> print(m1 + m2)
<script type="text/javascript" src="/static/jQuery.js"></script>
<script type="text/javascript" src="/static/script.js"></script>
<script type="text/javascript" src="/static/noConflict.js"></script>
<script type="text/javascript" src="/static/yet_another_script.js"></script>

Here the very important order of assets for m2 has changed.

Using proper merging, the order can be maintained. Furthermore Django should warn developers, if two media classes have the same assets in a reversed order.

This is how the order should be:

>>> from django.forms import Media
>>> m1 = Media(js=('jQuery.js', 'script.js', 'noConflict.js'))
>>> m2 = Media(js=('jQuery.js', 'yet_another_script.js', 'noConflict.js'))
>>> print(m1 + m2)
<script type="text/javascript" src="/static/jQuery.js"></script>
<script type="text/javascript" src="/static/script.js"></script>
<script type="text/javascript" src="/static/yet_another_script.js"></script>
<script type="text/javascript" src="/static/noConflict.js"></script>

or

>>> from django.forms import Media
>>> m1 = Media(js=('jQuery.js', 'script.js', 'noConflict.js'))
>>> m2 = Media(js=('jQuery.js', 'yet_another_script.js', 'noConflict.js'))
>>> print(m1 + m2)
<script type="text/javascript" src="/static/jQuery.js"></script>
<script type="text/javascript" src="/static/yet_another_script.js"></script>
<script type="text/javascript" src="/static/script.js"></script>
<script type="text/javascript" src="/static/noConflict.js"></script>

Both cases have no duplicates and the order of both individual form media assets is preserved.

Change History (5)

comment:1 Changed 3 years ago by Tim Graham

Triage Stage: UnreviewedAccepted
Type: BugCleanup/optimization

comment:2 Changed 3 years ago by Tim Graham <timograham@…>

Resolution: fixed
Status: assignedclosed

In c19b56f6:

Fixed #28377 -- Made combining form Media retain relative asset order.

Thanks Florian Apolloner, Mariusz Felisiak, and Tim Graham for reviews.

comment:3 Changed 3 years ago by Tim Graham <timograham@…>

In 751f7a6:

Added Media.repr().

It makes it easier to debug MediaOrderConflictWarnings
(refs #28377).

comment:4 Changed 3 years ago by Tim Graham <timograham@…>

In 03974d81:

Fixed #28866 -- Made InlineAdminFormSet include InlineModelAdmin's Media before its formset's Media.

This provides better backwards compatibility following refs #28377.

comment:5 Changed 3 years ago by Tim Graham <timograham@…>

In 6ece69a7:

[2.0.x] Fixed #28866 -- Made InlineAdminFormSet include InlineModelAdmin's Media before its formset's Media.

This provides better backwards compatibility following refs #28377.

Backport of 03974d81220ffd237754a82c77913799dd5909a4 from master

Note: See TracTickets for help on using tickets.
Back to Top