<commit_before>.. _topics-forms-media:

Form Media
==========

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 Django media definitions come in. Django allows you to
associate different media files with the forms and widgets that require
that media. 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.

.. admonition:: Media and Django Admin

    The Django Admin application defines a number of customized widgets
    for calendars, filtered selections, and so on. These widgets define
    media requirements, and the Django Admin uses the custom widgets
    in place of the Django defaults. The Admin templates will only include
    those media 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``.

.. admonition:: 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.

Media as a static definition
----------------------------

The easiest way to define media is as a static definition. Using this method,
the media declaration is an inner class. The properties of the inner class
define the media requirements.

Here's a simple example::

    class CalendarWidget(forms.TextInput):
        class Media:
            css = {
                'all': ('pretty.css',)
            }
            js = ('animations.js', 'actions.js')

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 media definition is converted at runtime into a widget property
named ``media``. The media for a CalendarWidget instance can be retrieved
through this property::

    >>> w = CalendarWidget()
    >>> print w.media
    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
    <script type="text/javascript" src="http://media.example.com/animations.js"></script>
    <script type="text/javascript" src="http://media.example.com/actions.js"></script>

Here's a list of all possible ``Media`` options. There are no required options.

``css``
~~~~~~~

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 media paths`_ for details of how to specify paths to media
files.

.. _the section on media paths: `Paths in media definitions`_

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::

    class Media:
        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::

    class Media:
        css = {
            'screen': ('pretty.css',),
            'tv,projector': ('lo_res.css',),
            'print': ('newspaper.css',)
        }

If this last CSS definition were to be rendered, it would become the following HTML::

    <link href="http://media.example.com/pretty.css" type="text/css" media="screen" rel="stylesheet" />
    <link href="http://media.example.com/lo_res.css" type="text/css" media="tv,projector" rel="stylesheet" />
    <link href="http://media.example.com/newspaper.css" type="text/css" media="print" rel="stylesheet" />

``js``
~~~~~~

A tuple describing the required JavaScript files. See
`the section on media paths`_ for details of how to specify paths to media
files.

``extend``
~~~~~~~~~~

A boolean defining inheritance behavior for media declarations.

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

    class FancyCalendarWidget(CalendarWidget):
        class Media:
            css = {
                'all': ('fancy.css',)
            }
            js = ('whizbang.js',)

    >>> w = FancyCalendarWidget()
    >>> print w.media
    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
    <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
    <script type="text/javascript" src="http://media.example.com/animations.js"></script>
    <script type="text/javascript" src="http://media.example.com/actions.js"></script>
    <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>

The FancyCalendar widget inherits all the media from it's parent widget. If
you don't want media to be inherited in this way, add an ``extend=False``
declaration to the media declaration::

    class FancyCalendar(Calendar):
        class Media:
            extend = False
            css = {
                'all': ('fancy.css',)
            }
            js = ('whizbang.js',)

    >>> w = FancyCalendarWidget()
    >>> print w.media
    <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
    <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>

If you require even more control over media inheritance, define your media
using a `dynamic property`_. Dynamic properties give you complete control over
which media files are inherited, and which are not.<commit_msg>Fixed #10437 -- Corrected typo in Widget media example. Thanks to <NAME>.<commit_after>.. _topics-forms-media:

Form Media
==========

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 Django media definitions come in. Django allows you to
associate different media files with the forms and widgets that require
that media. 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.

.. admonition:: Media and Django Admin

    The Django Admin application defines a number of customized widgets
    for calendars, filtered selections, and so on. These widgets define
    media requirements, and the Django Admin uses the custom widgets
    in place of the Django defaults. The Admin templates will only include
    those media 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``.

.. admonition:: 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.

Media as a static definition
----------------------------

The easiest way to define media is as a static definition. Using this method,
the media declaration is an inner class. The properties of the inner class
define the media requirements.

Here's a simple example::

    class CalendarWidget(forms.TextInput):
        class Media:
            css = {
                'all': ('pretty.css',)
            }
            js = ('animations.js', 'actions.js')

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 media definition is converted at runtime into a widget property
named ``media``. The media for a CalendarWidget instance can be retrieved
through this property::

    >>> w = CalendarWidget()
    >>> print w.media
    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
    <script type="text/javascript" src="http://media.example.com/animations.js"></script>
    <script type="text/javascript" src="http://media.example.com/actions.js"></script>

Here's a list of all possible ``Media`` options. There are no required options.

``css``
~~~~~~~

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 media paths`_ for details of how to specify paths to media
files.

.. _the section on media paths: `Paths in media definitions`_

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::

    class Media:
        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::

    class Media:
        css = {
            'screen': ('pretty.css',),
            'tv,projector': ('lo_res.css',),
            'print': ('newspaper.css',)
        }

If this last CSS definition were to be rendered, it would become the following HTML::

    <link href="http://media.example.com/pretty.css" type="text/css" media="screen" rel="stylesheet" />
    <link href="http://media.example.com/lo_res.css" type="text/css" media="tv,projector" rel="stylesheet" />
    <link href="http://media.example.com/newspaper.css" type="text/css" media="print" rel="stylesheet" />

``js``
~~~~~~

A tuple describing the required JavaScript files. See
`the section on media paths`_ for details of how to specify paths to media
files.

``extend``
~~~~~~~~~~

A boolean defining inheritance behavior for media declarations.

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

    class FancyCalendarWidget(CalendarWidget):
        class Media:
            css = {
                'all': ('fancy.css',)
            }
            js = ('whizbang.js',)

    >>> w = FancyCalendarWidget()
    >>> print w.media
    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
    <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
    <script type="text/javascript" src="http://media.example.com/animations.js"></script>
    <script type="text/javascript" src="http://media.example.com/actions.js"></script>
    <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>

The FancyCalendar widget inherits all the media from it's parent widget. If
you don't want media to be inherited in this way, add an ``extend=False``
declaration to the media declaration::

    class FancyCalendarWidget(CalendarWidget):
        class Media:
            extend = False
            css = {
                'all': ('fancy.css',)
            }
            js = ('whizbang.js',)

    >>> w = FancyCalendarWidget()
    >>> print w.media
    <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
    <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>

If you require even more control over media inheritance, define your media
using a `dynamic property`_. Dynamic properties give you complete control over
which media files are inherited, and which are not.
{'fraction_non_alphanumeric': 0.09971890372452565, 'fraction_numerical': 0.0006324666198172874, 'mean_word_length': 3.45554164057608, 'pattern_counts': {'":': 0, '<': 42, '<?xml version=': 0, '>': 78, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7431479', 'n_tokens_mistral': 3752, 'n_tokens_neox': 3622, 'n_words': 1723}