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.

This is where asset definitions come in. Django allows you to
associate different files – like stylesheets and scripts – with the
forms and widgets that require those assets. For example, if you want
to use a calendar to render DateFields, you can define a custom
Calendar widget. This widget can then be associated with the CSS and
JavaScript that is required to render the calendar. When the Calendar
widget is used on a form, Django is able to identify the CSS and
JavaScript files that are required, and provide the list of file names
in a form suitable for easy inclusion on your Web page.

Assets and Django Admin

The Django Admin application defines a number of customized
widgets for calendars, filtered selections, and so on. These
widgets define asset requirements, and the Django Admin uses the
custom widgets in place of the Django defaults. The Admin
templates will only include those files that are required to
render the widgets on any given page.

If you like the widgets that the Django Admin application uses,
feel free to use them in your own application! They’re all stored
in django.contrib.admin.widgets.

Which JavaScript toolkit?

Many JavaScript toolkits exist, and many of them include widgets (such
as calendar widgets) that can be used to enhance your application.
Django has deliberately avoided blessing any one JavaScript toolkit.
Each toolkit has its own relative strengths and weaknesses - use
whichever toolkit suits your requirements. Django is able to integrate
with any JavaScript toolkit.

This code defines a CalendarWidget, which will be based on TextInput.
Every time the CalendarWidget is used on a form, that form will be directed
to include the CSS file pretty.css, and the JavaScript files
animations.js and actions.js.

This static definition is converted at runtime into a widget property
named media. The list of assets for a CalendarWidget instance
can be retrieved through this property:

A dictionary describing the CSS files required for various forms of output
media.

The values in the dictionary should be a tuple/list of file names. See
the section on paths for details of how to
specify paths to these files.

The keys in the dictionary are the output media types. These are the same
types accepted by CSS files in media declarations: ‘all’, ‘aural’, ‘braille’,
‘embossed’, ‘handheld’, ‘print’, ‘projection’, ‘screen’, ‘tty’ and ‘tv’. If
you need to have different stylesheets for different media types, provide
a list of CSS files for each output medium. The following example would
provide two CSS options – one for the screen, and one for print:

classMedia:css={'screen':('pretty.css',),'print':('newspaper.css',)}

If a group of CSS files are appropriate for multiple output media types,
the dictionary key can be a comma separated list of output media types.
In the following example, TV’s and projectors will have the same media
requirements:

By default, any object using a static Media definition will
inherit all the assets associated with the parent widget. This occurs
regardless of how the parent defines its own requirements. For
example, if we were to extend our basic Calendar widget from the
example above:

If you need to perform some more sophisticated manipulation of asset
requirements, you can define the media property directly. This is
done by defining a widget property that returns an instance of
forms.Media. The constructor for forms.Media accepts css
and js keyword arguments in the same format as that used in a
static media definition.

For example, the static definition for our Calendar Widget could also
be defined in a dynamic fashion:

Paths used to specify assets can be either relative or absolute. If a
path starts with /, http:// or https://, it will be
interpreted as an absolute path, and left as-is. All other paths will
be prepended with the value of the appropriate prefix.

As part of the introduction of the
staticfiles app two new settings were added
to refer to “static files” (images, CSS, Javascript, etc.) that are needed
to render a complete web page: STATIC_URL and STATIC_ROOT.

To find the appropriate prefix to use, Django will check if the
STATIC_URL setting is not None and automatically fall back
to using MEDIA_URL. For example, if the MEDIA_URL for
your site was 'http://uploads.example.com/' and STATIC_URL
was None:

When you interrogate the media attribute of a widget or form, the
value that is returned is a forms.Media object. As we have already
seen, the string representation of a Media object is the HTML
required to include the relevant files in the <head> block of your
HTML page.

Widgets aren’t the only objects that can have media definitions –
forms can also define media. The rules for media definitions
on forms are the same as the rules for widgets: declarations can be
static or dynamic; path and inheritance rules for those declarations
are exactly the same.

Regardless of whether you define a media declaration, all Form
objects have a media property. The default value for this property
is the result of adding the media definitions for all widgets that
are part of the form: