PageRenderTime 19ms CodeModel.GetById 10ms app.highlight 3ms RepoModel.GetById 1ms app.codeStats 0ms

/docs/topics/forms/media.txt

https://code.google.com/p/mango-py/
Plain Text | 332 lines | 258 code | 74 blank | 0 comment | 0 complexity | 6b38fe7f34b870f3dd905284739cd16d MD5 | raw file
  1Form Media
  2==========
  3
  4Rendering an attractive and easy-to-use Web form requires more than just
  5HTML - it also requires CSS stylesheets, and if you want to use fancy
  6"Web2.0" widgets, you may also need to include some JavaScript on each
  7page. The exact combination of CSS and JavaScript that is required for
  8any given page will depend upon the widgets that are in use on that page.
  9
 10This is where Django media definitions come in. Django allows you to
 11associate different media files with the forms and widgets that require
 12that media. For example, if you want to use a calendar to render DateFields,
 13you can define a custom Calendar widget. This widget can then be associated
 14with the CSS and JavaScript that is required to render the calendar. When
 15the Calendar widget is used on a form, Django is able to identify the CSS and
 16JavaScript files that are required, and provide the list of file names
 17in a form suitable for easy inclusion on your Web page.
 18
 19.. admonition:: Media and Django Admin
 20
 21    The Django Admin application defines a number of customized widgets
 22    for calendars, filtered selections, and so on. These widgets define
 23    media requirements, and the Django Admin uses the custom widgets
 24    in place of the Django defaults. The Admin templates will only include
 25    those media files that are required to render the widgets on any
 26    given page.
 27
 28    If you like the widgets that the Django Admin application uses,
 29    feel free to use them in your own application! They're all stored
 30    in ``django.contrib.admin.widgets``.
 31
 32.. admonition:: Which JavaScript toolkit?
 33
 34    Many JavaScript toolkits exist, and many of them include widgets (such
 35    as calendar widgets) that can be used to enhance your application.
 36    Django has deliberately avoided blessing any one JavaScript toolkit.
 37    Each toolkit has its own relative strengths and weaknesses - use
 38    whichever toolkit suits your requirements. Django is able to integrate
 39    with any JavaScript toolkit.
 40
 41Media as a static definition
 42----------------------------
 43
 44The easiest way to define media is as a static definition. Using this method,
 45the media declaration is an inner class. The properties of the inner class
 46define the media requirements.
 47
 48Here's a simple example::
 49
 50    class CalendarWidget(forms.TextInput):
 51        class Media:
 52            css = {
 53                'all': ('pretty.css',)
 54            }
 55            js = ('animations.js', 'actions.js')
 56
 57This code defines a ``CalendarWidget``, which will be based on ``TextInput``.
 58Every time the CalendarWidget is used on a form, that form will be directed
 59to include the CSS file ``pretty.css``, and the JavaScript files
 60``animations.js`` and ``actions.js``.
 61
 62This static media definition is converted at runtime into a widget property
 63named ``media``. The media for a CalendarWidget instance can be retrieved
 64through this property::
 65
 66    >>> w = CalendarWidget()
 67    >>> print w.media
 68    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
 69    <script type="text/javascript" src="http://media.example.com/animations.js"></script>
 70    <script type="text/javascript" src="http://media.example.com/actions.js"></script>
 71
 72Here's a list of all possible ``Media`` options. There are no required options.
 73
 74``css``
 75~~~~~~~
 76
 77A dictionary describing the CSS files required for various forms of output
 78media.
 79
 80The values in the dictionary should be a tuple/list of file names. See
 81`the section on media paths`_ for details of how to specify paths to media
 82files.
 83
 84.. _the section on media paths: `Paths in media definitions`_
 85
 86The keys in the dictionary are the output media types. These are the same
 87types accepted by CSS files in media declarations: 'all', 'aural', 'braille',
 88'embossed', 'handheld', 'print', 'projection', 'screen', 'tty' and 'tv'. If
 89you need to have different stylesheets for different media types, provide
 90a list of CSS files for each output medium. The following example would
 91provide two CSS options -- one for the screen, and one for print::
 92
 93    class Media:
 94        css = {
 95            'screen': ('pretty.css',),
 96            'print': ('newspaper.css',)
 97        }
 98
 99If a group of CSS files are appropriate for multiple output media types,
100the dictionary key can be a comma separated list of output media types.
101In the following example, TV's and projectors will have the same media
102requirements::
103
104    class Media:
105        css = {
106            'screen': ('pretty.css',),
107            'tv,projector': ('lo_res.css',),
108            'print': ('newspaper.css',)
109        }
110
111If this last CSS definition were to be rendered, it would become the following HTML::
112
113    <link href="http://media.example.com/pretty.css" type="text/css" media="screen" rel="stylesheet" />
114    <link href="http://media.example.com/lo_res.css" type="text/css" media="tv,projector" rel="stylesheet" />
115    <link href="http://media.example.com/newspaper.css" type="text/css" media="print" rel="stylesheet" />
116
117``js``
118~~~~~~
119
120A tuple describing the required JavaScript files. See
121`the section on media paths`_ for details of how to specify paths to media
122files.
123
124``extend``
125~~~~~~~~~~
126
127A boolean defining inheritance behavior for media declarations.
128
129By default, any object using a static media definition will inherit all the
130media associated with the parent widget. This occurs regardless of how the
131parent defines its media requirements. For example, if we were to extend our
132basic Calendar widget from the example above::
133
134    >>> class FancyCalendarWidget(CalendarWidget):
135    ...     class Media:
136    ...         css = {
137    ...             'all': ('fancy.css',)
138    ...         }
139    ...         js = ('whizbang.js',)
140
141    >>> w = FancyCalendarWidget()
142    >>> print w.media
143    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
144    <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
145    <script type="text/javascript" src="http://media.example.com/animations.js"></script>
146    <script type="text/javascript" src="http://media.example.com/actions.js"></script>
147    <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>
148
149The FancyCalendar widget inherits all the media from it's parent widget. If
150you don't want media to be inherited in this way, add an ``extend=False``
151declaration to the media declaration::
152
153    >>> class FancyCalendarWidget(CalendarWidget):
154    ...     class Media:
155    ...         extend = False
156    ...         css = {
157    ...             'all': ('fancy.css',)
158    ...         }
159    ...         js = ('whizbang.js',)
160
161    >>> w = FancyCalendarWidget()
162    >>> print w.media
163    <link href="http://media.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
164    <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>
165
166If you require even more control over media inheritance, define your media
167using a `dynamic property`_. Dynamic properties give you complete control over
168which media files are inherited, and which are not.
169
170.. _dynamic property: `Media as a dynamic property`_
171
172Media as a dynamic property
173---------------------------
174
175If you need to perform some more sophisticated manipulation of media
176requirements, you can define the media property directly. This is done
177by defining a widget property that returns an instance of ``forms.Media``.
178The constructor for ``forms.Media`` accepts ``css`` and ``js`` keyword
179arguments in the same format as that used in a static media definition.
180
181For example, the static media definition for our Calendar Widget could
182also be defined in a dynamic fashion::
183
184    class CalendarWidget(forms.TextInput):
185        def _media(self):
186            return forms.Media(css={'all': ('pretty.css',)},
187                               js=('animations.js', 'actions.js'))
188        media = property(_media)
189
190See the section on `Media objects`_ for more details on how to construct
191return values for dynamic media properties.
192
193.. _form-media-paths:
194
195Paths in media definitions
196--------------------------
197
198.. versionchanged:: 1.3
199
200Paths used to specify media can be either relative or absolute. If a path
201starts with '/', 'http://' or 'https://', it will be interpreted as an absolute
202path, and left as-is. All other paths will be prepended with the value of
203the appropriate prefix.
204
205As part of the introduction of the
206:doc:`staticfiles app </ref/contrib/staticfiles>` two new settings were added
207to refer to "static files" (images, CSS, Javascript, etc.) that are needed
208to render a complete web page: :setting:`STATIC_URL` and :setting:`STATIC_ROOT`.
209
210To find the appropriate prefix to use, Django will check if the
211:setting:`STATIC_URL` setting is not ``None`` and automatically fall back
212to using :setting:`MEDIA_URL`. For example, if the :setting:`MEDIA_URL` for
213your site was ``'http://uploads.example.com/'`` and :setting:`STATIC_URL`
214was ``None``::
215
216    >>> class CalendarWidget(forms.TextInput):
217    ...     class Media:
218    ...         css = {
219    ...             'all': ('/css/pretty.css',),
220    ...         }
221    ...         js = ('animations.js', 'http://othersite.com/actions.js')
222
223    >>> w = CalendarWidget()
224    >>> print w.media
225    <link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
226    <script type="text/javascript" src="http://uploads.example.com/animations.js"></script>
227    <script type="text/javascript" src="http://othersite.com/actions.js"></script>
228
229But if :setting:`STATIC_URL` is ``'http://static.example.com/'``::
230
231    >>> w = CalendarWidget()
232    >>> print w.media
233    <link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
234    <script type="text/javascript" src="http://static.example.com/animations.js"></script>
235    <script type="text/javascript" src="http://othersite.com/actions.js"></script>
236
237
238Media objects
239-------------
240
241When you interrogate the media attribute of a widget or form, the value that
242is returned is a ``forms.Media`` object. As we have already seen, the string
243representation of a Media object is the HTML required to include media
244in the ``<head>`` block of your HTML page.
245
246However, Media objects have some other interesting properties.
247
248Media subsets
249~~~~~~~~~~~~~
250
251If you only want media of a particular type, you can use the subscript operator
252to filter out a medium of interest. For example::
253
254    >>> w = CalendarWidget()
255    >>> print w.media
256    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
257    <script type="text/javascript" src="http://media.example.com/animations.js"></script>
258    <script type="text/javascript" src="http://media.example.com/actions.js"></script>
259
260    >>> print w.media['css']
261    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
262
263When you use the subscript operator, the value that is returned is a new
264Media object -- but one that only contains the media of interest.
265
266Combining media objects
267~~~~~~~~~~~~~~~~~~~~~~~
268
269Media objects can also be added together. When two media objects are added,
270the resulting Media object contains the union of the media from both files::
271
272    >>> class CalendarWidget(forms.TextInput):
273    ...     class Media:
274    ...         css = {
275    ...             'all': ('pretty.css',)
276    ...         }
277    ...         js = ('animations.js', 'actions.js')
278
279    >>> class OtherWidget(forms.TextInput):
280    ...     class Media:
281    ...         js = ('whizbang.js',)
282
283    >>> w1 = CalendarWidget()
284    >>> w2 = OtherWidget()
285    >>> print w1.media + w2.media
286    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
287    <script type="text/javascript" src="http://media.example.com/animations.js"></script>
288    <script type="text/javascript" src="http://media.example.com/actions.js"></script>
289    <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>
290
291Media on Forms
292--------------
293
294Widgets aren't the only objects that can have media definitions -- forms
295can also define media. The rules for media definitions on forms are the
296same as the rules for widgets: declarations can be static or dynamic;
297path and inheritance rules for those declarations are exactly the same.
298
299Regardless of whether you define a media declaration, *all* Form objects
300have a media property. The default value for this property is the result
301of adding the media definitions for all widgets that are part of the form::
302
303    >>> class ContactForm(forms.Form):
304    ...     date = DateField(widget=CalendarWidget)
305    ...     name = CharField(max_length=40, widget=OtherWidget)
306
307    >>> f = ContactForm()
308    >>> f.media
309    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
310    <script type="text/javascript" src="http://media.example.com/animations.js"></script>
311    <script type="text/javascript" src="http://media.example.com/actions.js"></script>
312    <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>
313
314If you want to associate additional media with a form -- for example, CSS for form
315layout -- simply add a media declaration to the form::
316
317    >>> class ContactForm(forms.Form):
318    ...     date = DateField(widget=CalendarWidget)
319    ...     name = CharField(max_length=40, widget=OtherWidget)
320    ...
321    ...     class Media:
322    ...         css = {
323    ...             'all': ('layout.css',)
324    ...         }
325
326    >>> f = ContactForm()
327    >>> f.media
328    <link href="http://media.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
329    <link href="http://media.example.com/layout.css" type="text/css" media="all" rel="stylesheet" />
330    <script type="text/javascript" src="http://media.example.com/animations.js"></script>
331    <script type="text/javascript" src="http://media.example.com/actions.js"></script>
332    <script type="text/javascript" src="http://media.example.com/whizbang.js"></script>