Skip to content

Support lists of css files on forms.Media #159

Description

@blighj

Code of Conduct

  • I agree to follow Django's Code of Conduct

Feature Description

Forms.Media could take a list instead of a dict for its css asset list.

Problem

@codingjoe and @nessita added object-based stylesheet media assets last week. in #37085
This opens up another simlification discussed in the various Form.Media Rejuvenating discussions.
@aaugustin suggesting on the mailinglist which I came to via the forum discussion

It would simlify what is a slightly awkward syntax at present.
The css could change from a dict keyed on media type to a list of "file path strings" or Stylesheet's.
If you need a media=print, use Stylesheet

Our default example usage in the docs becomes:

from django import forms

class CalendarWidget(forms.TextInput):
    class Media:
        css = ["pretty.css"]
        js = ["animations.js", "actions.js"]

And our example of setting media= becomes

class Media:
    css = [
        Stylesheet("pretty.css", media="screen"),
        Stylesheet("newspaper.css", media="print"),
    ]

or even

class Media:
    css = [
        "pretty.css",
        Stylesheet("newspaper.css", media="print"),
    ]

Request or proposal

proposal

Additional Details

The dict approach could be kept for backwards compatiility but no longer documented. Or if could be deprecated as normal.

I've done up a diff for the media docs so you can see the full affect in this saved diff

By default you would not be adding media="all" to the tag, it defaults to that anyway.

Implementation Suggestions

To support dict and list we could normalise everything to lists of MediaAsset/Stylesheet with the correct media set.

  def __init__(self, media=None, css=None, js=None):
      if isinstance(css, list):
          self._css_lists = [[
              a if isinstance(a, MediaAsset) else Stylesheet(a)
              for a in css
          ]]
      elif isinstance(css, dict):
          self._css_lists = [[
              a if isinstance(a, MediaAsset) else Stylesheet(a, media=medium)
              for medium, paths in css.items()
              for a in paths
          ]]

The css handling functions can then be simplified.

_css property matches the _js property:

    @property
    def _css(self):
        return self.merge(*self._css_lists)

This is marked private but something like @dmptrluke's django-csp-helpers package would be affected.

and render simplifies to:

    def render_css(self, *, attrs=None):
        return [path.render(attrs=attrs) for path in self._css]

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    Status
    Idea

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions