Ticket #4418: newforms-admin-media.diff
File newforms-admin-media.diff, 27.2 KB (added by , 17 years ago) |
---|
-
django/newforms/formsets.py
1 1 from forms import Form, ValidationError 2 2 from fields import IntegerField, BooleanField 3 from widgets import HiddenInput 3 from widgets import HiddenInput, Media 4 4 5 5 # special field names 6 6 FORM_COUNT_FIELD_NAME = 'COUNT' … … 149 149 self.full_clean() 150 150 return self._is_valid 151 151 152 def _get_media(self): 153 # All the forms on a FormSet are the same, so you only need to 154 # interrogate the first form for media. 155 if self.forms: 156 return self.forms[0].media 157 else: 158 return Media() 159 media = property(_get_media) 160 152 161 def formset_for_form(form, formset=BaseFormSet, num_extra=1, orderable=False, deletable=False): 153 162 """Return a FormSet for the given form class.""" 154 163 attrs = {'form_class': form, 'num_extra': num_extra, 'orderable': orderable, 'deletable': deletable} -
django/newforms/forms.py
9 9 from django.utils.encoding import StrAndUnicode, smart_unicode, force_unicode 10 10 11 11 from fields import Field 12 from widgets import TextInput, Textarea12 from widgets import Media, TextInput, Textarea 13 13 from util import flatatt, ErrorDict, ErrorList, ValidationError 14 14 15 15 __all__ = ('BaseForm', 'Form') … … 234 234 self.is_bound = False 235 235 self.__errors = None 236 236 237 def _get_media(self): 238 """ 239 Provide a description of all media required to render the widgets on this form 240 """ 241 media = Media() 242 for field in self.fields.values(): 243 media = media + field.widget.media 244 return media 245 media = property(_get_media) 246 237 247 class Form(BaseForm): 238 248 "A collection of Fields, plus their associated data." 239 249 # This is a separate class from BaseForm in order to abstract the way -
django/newforms/widgets.py
8 8 from sets import Set as set # Python 2.3 fallback 9 9 10 10 from itertools import chain 11 from django.conf import settings 11 12 from django.utils.datastructures import MultiValueDict 12 13 from django.utils.html import escape 13 14 from django.utils.translation import ugettext … … 15 16 from util import flatatt 16 17 17 18 __all__ = ( 18 ' Widget', 'TextInput', 'PasswordInput',19 'Media', 'Widget', 'TextInput', 'PasswordInput', 19 20 'HiddenInput', 'MultipleHiddenInput', 20 21 'FileInput', 'Textarea', 'CheckboxInput', 21 22 'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', 22 23 'CheckboxSelectMultiple', 'MultiWidget', 'SplitDateTimeWidget', 23 24 ) 24 25 26 MEDIA_TYPES = ('css','js') 27 28 class Media(StrAndUnicode): 29 def __init__(self, media=None, **kwargs): 30 if media: 31 media_attrs = media.__dict__ 32 del media_attrs['__module__'] 33 del media_attrs['__doc__'] 34 else: 35 media_attrs = kwargs 36 37 self._css = {} 38 self._js = [] 39 40 for name in MEDIA_TYPES: 41 getattr(self, 'add_' + name)(media_attrs.pop(name, None)) 42 43 # Any leftover attributes must be invalid. 44 if media_attrs != {}: 45 raise TypeError, "'class Media' has invalid attribute(s): %s" % ','.join(media_attrs.keys()) 46 47 def __unicode__(self): 48 return self.render() 49 50 def render(self): 51 output = [] 52 for name in MEDIA_TYPES: 53 output.extend(getattr(self, 'render_' + name)()) 54 return u'\n'.join(output) 55 56 def render_js(self): 57 output = [] 58 for path in self._js: 59 output.append(u'<script type="text/javascript" src="%s"></script>' % self.absolute_path(path)) 60 return output 61 62 def render_css(self): 63 output = [] 64 # To keep rendering order consistent, we can't just iterate over items(). 65 # We need to sort the keys, and iterate over the sorted list. 66 media = self._css.keys() 67 media.sort() 68 for medium in media: 69 for path in self._css[medium]: 70 output.append(u'<link href="%s" type="text/css" media="%s" rel="stylesheet" />' % (self.absolute_path(path), medium)) 71 return output 72 73 def absolute_path(self, path): 74 return (path.startswith(u'http://') or path.startswith(u'https://')) and path or u''.join([settings.MEDIA_URL,path]) 75 76 def __getitem__(self, name): 77 "Returns a Media object that only contains media of the given type" 78 if name in MEDIA_TYPES: 79 return Media(**{name: getattr(self, '_' + name)}) 80 raise KeyError('Unknown media type "%s"' % name) 81 82 def add_js(self, data): 83 if data: 84 self._js.extend([path for path in data if path not in self._js]) 85 86 def add_css(self, data): 87 if data: 88 for medium, paths in data.items(): 89 self._css.setdefault(medium, []).extend([path for path in paths if path not in self._css[medium]]) 90 91 def __add__(self, other): 92 combined = Media() 93 for name in MEDIA_TYPES: 94 getattr(combined, 'add_' + name)(getattr(self, '_' + name, None)) 95 getattr(combined, 'add_' + name)(getattr(other, '_' + name, None)) 96 return combined 97 98 class WidgetBase(type): 99 "Metaclass for all widgets" 100 def __new__(cls, name, bases, attrs): 101 media_definition = attrs.pop('Media', None) 102 media_property = attrs.pop('media', None) 103 104 # If this class definition doesn't have a media definition, 105 # search the base classes. 106 if media_definition == None and media_property == None: 107 for base in bases: 108 media_definition = getattr(base, 'Media', None) 109 media_property = getattr(base, 'media', None) 110 if media_definition or media_property: 111 break; 112 113 new_class = type.__new__(cls, name, bases, attrs) 114 setattr(new_class, 'media', media_property and media_property or Media(media_definition)) 115 return new_class 116 25 117 class Widget(object): 118 __metaclass__ = WidgetBase 26 119 is_hidden = False # Determines whether this corresponds to an <input type="hidden">. 27 120 28 121 def __init__(self, attrs=None): … … 377 470 """ 378 471 raise NotImplementedError('Subclasses must implement this method.') 379 472 473 def _get_media(self): 474 "Media for a multiwidget is the combination of all media of the subwidgets" 475 media = Media() 476 for w in self.widgets: 477 media = media + w.media 478 return media 479 media = property(_get_media) 480 380 481 class SplitDateTimeWidget(MultiWidget): 381 482 """ 382 483 A Widget that splits datetime input into two <input type="text"> boxes. … … 389 490 if value: 390 491 return [value.date(), value.time()] 391 492 return [None, None] 493 494 No newline at end of file -
django/contrib/admin/options.py
2 2 from django import newforms as forms 3 3 from django.newforms.formsets import all_valid 4 4 from django.newforms.models import inline_formset 5 from django.newforms.widgets import Media 5 6 from django.contrib.admin import widgets 6 7 from django.core.exceptions import ImproperlyConfigured, PermissionDenied 7 8 from django.db import models … … 48 49 def first_field(self): 49 50 for bf in self.form: 50 51 return bf 52 53 def _get_media(self): 54 media = self.form.media 55 for fs in self.fieldsets: 56 media = media + fs.media 57 return media 58 media = property(_get_media) 51 59 52 60 class Fieldset(object): 53 61 def __init__(self, name=None, fields=(), classes=(), description=None): … … 55 63 self.classes = u' '.join(classes) 56 64 self.description = description 57 65 66 def _get_media(self): 67 from django.conf import settings 68 if 'collapse' in self.classes: 69 return Media(js=['%sjs/admin/CollapsedFieldsets.js' % settings.ADMIN_MEDIA_PREFIX]) 70 return Media() 71 media = property(_get_media) 72 58 73 class BoundFieldset(object): 59 74 def __init__(self, form, fieldset): 60 75 self.form, self.fieldset = form, fieldset … … 123 138 124 139 # For DateFields, add a custom CSS class. 125 140 if isinstance(db_field, models.DateField): 126 kwargs['widget'] = forms.TextInput(attrs={'class': 'vDateField', 'size': '10'})141 kwargs['widget'] = widgets.AdminDateWidget 127 142 return db_field.formfield(**kwargs) 128 143 129 144 # For TimeFields, add a custom CSS class. 130 145 if isinstance(db_field, models.TimeField): 131 kwargs['widget'] = forms.TextInput(attrs={'class': 'vTimeField', 'size': '8'})146 kwargs['widget'] = widgets.AdminTimeWidget 132 147 return db_field.formfield(**kwargs) 133 148 134 149 # For ForeignKey or ManyToManyFields, use a special widget. … … 194 209 else: 195 210 return self.change_view(request, unquote(url)) 196 211 197 def javascript(self, request, fieldsets): 198 """ 199 Returns a list of URLs to include via <script> statements. 212 def media(self, request): 213 from django.conf import settings 200 214 201 The URLs can be absolute ('/js/admin/') or explicit202 ('http://example.com/foo.js').203 """204 from django.conf import settings205 215 js = ['js/core.js', 'js/admin/RelatedObjectLookups.js'] 206 216 if self.prepopulated_fields: 207 217 js.append('js/urlify.js') 208 if self.opts.has_field_type(models.DateTimeField) or self.opts.has_field_type(models.TimeField) or self.opts.has_field_type(models.DateField):209 js.extend(['js/calendar.js', 'js/admin/DateTimeShortcuts.js'])210 218 if self.opts.get_ordered_objects(): 211 219 js.extend(['js/getElementsBySelector.js', 'js/dom-drag.js' , 'js/admin/ordering.js']) 212 220 if self.js: 213 221 js.extend(self.js) 214 222 if self.filter_vertical or self.filter_horizontal: 215 223 js.extend(['js/SelectBox.js' , 'js/SelectFilter2.js']) 216 for fs in fieldsets: 217 if 'collapse' in fs.classes: 218 js.append('js/admin/CollapsedFieldsets.js') 219 break 220 prefix = settings.ADMIN_MEDIA_PREFIX 221 return ['%s%s' % (prefix, url) for url in js] 222 223 def javascript_add(self, request): 224 return self.javascript(request, self.fieldsets_add(request)) 225 226 def javascript_change(self, request, obj): 227 return self.javascript(request, self.fieldsets_change(request, obj)) 228 224 225 return Media(js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js]) 226 229 227 def fieldsets(self, request): 230 228 """ 231 229 Generator that yields Fieldset objects for use on add and change admin … … 244 242 245 243 def fieldsets_add(self, request): 246 244 "Hook for specifying Fieldsets for the add form." 247 for fs in self.fieldsets(request): 248 yield fs 245 return list(self.fieldsets(request)) 249 246 250 247 def fieldsets_change(self, request, obj): 251 248 "Hook for specifying Fieldsets for the change form." 252 for fs in self.fieldsets(request): 253 yield fs 249 return list(self.fieldsets(request)) 254 250 255 251 def has_add_permission(self, request): 256 252 "Returns True if the given request has permission to add an object." … … 433 429 inline_formset = FormSet() 434 430 inline_formsets.append(inline_formset) 435 431 432 adminForm = AdminForm(form, list(self.fieldsets_add(request)), self.prepopulated_fields) 433 media = self.media(request) + adminForm.media 434 for fs in inline_formsets: 435 media = media + fs.media 436 436 437 c = template.RequestContext(request, { 437 438 'title': _('Add %s') % opts.verbose_name, 438 'adminform': AdminForm(form, self.fieldsets_add(request), self.prepopulated_fields),439 'adminform': adminForm, 439 440 'is_popup': request.REQUEST.has_key('_popup'), 440 441 'show_delete': False, 441 ' javascript_imports': self.javascript_add(request),442 'media': media, 442 443 'bound_inlines': [BoundInline(i, fs) for i, fs in zip(self.inlines, inline_formsets)], 443 444 }) 444 445 return render_change_form(self, model, model.AddManipulator(), c, add=True) … … 500 501 #related.get_accessor_name()) 501 502 #orig_list = func() 502 503 #oldform.order_objects.extend(orig_list) 504 505 adminForm = AdminForm(form, self.fieldsets_change(request, obj), self.prepopulated_fields) 506 media = self.media(request) + adminForm.media 507 for fs in inline_formsets: 508 media = media + fs.media 509 503 510 c = template.RequestContext(request, { 504 511 'title': _('Change %s') % opts.verbose_name, 505 'adminform': AdminForm(form, self.fieldsets_change(request, obj), self.prepopulated_fields),512 'adminform': adminForm, 506 513 'object_id': object_id, 507 514 'original': obj, 508 515 'is_popup': request.REQUEST.has_key('_popup'), 509 ' javascript_imports': self.javascript_change(request, obj),516 'media': media, 510 517 'bound_inlines': [BoundInline(i, fs) for i, fs in zip(self.inlines, inline_formsets)], 511 518 }) 512 519 return render_change_form(self, model, model.ChangeManipulator(object_id), c, change=True) -
django/contrib/admin/widgets.py
5 5 from django import newforms as forms 6 6 from django.utils.text import capfirst 7 7 from django.utils.translation import ugettext as _ 8 from django.conf import settings 8 9 9 10 class FilteredSelectMultiple(forms.SelectMultiple): 10 11 """ … … 28 29 (name, self.verbose_name.replace('"', '\\"'), int(self.is_stacked), settings.ADMIN_MEDIA_PREFIX)) 29 30 return u''.join(output) 30 31 32 class AdminDateWidget(forms.TextInput): 33 class Media: 34 js = (settings.ADMIN_MEDIA_PREFIX + "js/calendar.js", 35 settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js") 36 37 def __init__(self, attrs={}): 38 super(AdminDateWidget, self).__init__(attrs={'class': 'vDateField', 'size': '10'}) 39 40 class AdminTimeWidget(forms.TextInput): 41 class Media: 42 js = (settings.ADMIN_MEDIA_PREFIX + "js/calendar.js", 43 settings.ADMIN_MEDIA_PREFIX + "js/admin/DateTimeShortcuts.js") 44 45 def __init__(self, attrs={}): 46 super(AdminTimeWidget, self).__init__(attrs={'class': 'vTimeField', 'size': '8'}) 47 31 48 class AdminSplitDateTime(forms.SplitDateTimeWidget): 32 49 """ 33 50 A SplitDateTime Widget that has some admin-specific styling. 34 51 """ 35 52 def __init__(self, attrs=None): 36 widgets = [forms.TextInput(attrs={'class': 'vDateField', 'size': '10'}), 37 forms.TextInput(attrs={'class': 'vTimeField', 'size': '8'})] 53 widgets = [AdminDateWidget, AdminTimeWidget] 38 54 # Note that we're calling MultiWidget, not SplitDateTimeWidget, because 39 55 # we want to define widgets. 40 56 forms.MultiWidget.__init__(self, widgets, attrs) -
django/contrib/admin/templates/admin/auth/user/change_password.html
2 2 {% load i18n admin_modify adminmedia %} 3 3 {% block extrahead %}{{ block.super }} 4 4 <script type="text/javascript" src="../../../../jsi18n/"></script> 5 {% for js in javascript_imports %}{% include_admin_script js %}{% endfor %}6 5 {% endblock %} 7 6 {% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %} 8 7 {% block bodyclass %}{{ opts.app_label }}-{{ opts.object_name.lower }} change-form{% endblock %} -
django/contrib/admin/templates/admin/change_form.html
3 3 4 4 {% block extrahead %}{{ block.super }} 5 5 <script type="text/javascript" src="../../../jsi18n/"></script> 6 {% for js in javascript_imports %}<script type="text/javascript" src="{{ js }}"></script> 7 {% endfor %} 6 {{ media }} 8 7 {% endblock %} 9 8 10 9 {% block stylesheet %}{% admin_media_prefix %}css/forms.css{% endblock %} -
tests/regressiontests/forms/media.py
1 # -*- coding: utf-8 -*- 2 # Tests for the media handling on widgets and forms 3 4 media_tests = r""" 5 >>> from django.newforms import TextInput, Media, TextInput, CharField, Form, MultiWidget 6 >>> from django.conf import settings 7 >>> settings.MEDIA_URL = 'http://media.example.com' 8 9 # A widget can exist without a media definition 10 >>> class MyWidget(TextInput): 11 ... pass 12 13 >>> w = MyWidget() 14 >>> print w.media 15 <BLANKLINE> 16 17 # A widget can define media if it needs to. 18 # Any absolute path will be preserved; relative paths are combined 19 # with the value of settings.MEDIA_URL 20 >>> class MyWidget1(TextInput): 21 ... class Media: 22 ... css = { 23 ... 'all': ('/path/to/css1','/path/to/css2') 24 ... } 25 ... js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3') 26 27 >>> w1 = MyWidget1() 28 >>> print w1.media 29 <link href="http://media.example.com/path/to/css1" type="text/css" media="all" rel="stylesheet" /> 30 <link href="http://media.example.com/path/to/css2" type="text/css" media="all" rel="stylesheet" /> 31 <script type="text/javascript" src="http://media.example.com/path/to/js1"></script> 32 <script type="text/javascript" src="http://media.other.com/path/to/js2"></script> 33 <script type="text/javascript" src="https://secure.other.com/path/to/js3"></script> 34 35 # Media objects can be interrogated by media type 36 >>> print w1.media['css'] 37 <link href="http://media.example.com/path/to/css1" type="text/css" media="all" rel="stylesheet" /> 38 <link href="http://media.example.com/path/to/css2" type="text/css" media="all" rel="stylesheet" /> 39 40 >>> print w1.media['js'] 41 <script type="text/javascript" src="http://media.example.com/path/to/js1"></script> 42 <script type="text/javascript" src="http://media.other.com/path/to/js2"></script> 43 <script type="text/javascript" src="https://secure.other.com/path/to/js3"></script> 44 45 # Media objects can be combined. Any given media resource will appear only 46 # once. Duplicated media definitions are ignored. 47 >>> class MyWidget2(TextInput): 48 ... class Media: 49 ... css = { 50 ... 'all': ('/path/to/css2','/path/to/css3') 51 ... } 52 ... js = ('/path/to/js1','/path/to/js4') 53 54 >>> class MyWidget3(TextInput): 55 ... class Media: 56 ... css = { 57 ... 'all': ('/path/to/css3','/path/to/css1') 58 ... } 59 ... js = ('/path/to/js1','/path/to/js4') 60 61 >>> w2 = MyWidget2() 62 >>> w3 = MyWidget3() 63 >>> print w1.media + w2.media + w3.media 64 <link href="http://media.example.com/path/to/css1" type="text/css" media="all" rel="stylesheet" /> 65 <link href="http://media.example.com/path/to/css2" type="text/css" media="all" rel="stylesheet" /> 66 <link href="http://media.example.com/path/to/css3" type="text/css" media="all" rel="stylesheet" /> 67 <script type="text/javascript" src="http://media.example.com/path/to/js1"></script> 68 <script type="text/javascript" src="http://media.other.com/path/to/js2"></script> 69 <script type="text/javascript" src="https://secure.other.com/path/to/js3"></script> 70 <script type="text/javascript" src="http://media.example.com/path/to/js4"></script> 71 72 # Check that media addition hasn't affected the original objects 73 >>> print w1.media 74 <link href="http://media.example.com/path/to/css1" type="text/css" media="all" rel="stylesheet" /> 75 <link href="http://media.example.com/path/to/css2" type="text/css" media="all" rel="stylesheet" /> 76 <script type="text/javascript" src="http://media.example.com/path/to/js1"></script> 77 <script type="text/javascript" src="http://media.other.com/path/to/js2"></script> 78 <script type="text/javascript" src="https://secure.other.com/path/to/js3"></script> 79 80 81 # If a widget extends another, it inherits the parent widget's media 82 >>> class MyWidget4(MyWidget1): 83 ... pass 84 85 >>> w4 = MyWidget4() 86 >>> print w4.media 87 <link href="http://media.example.com/path/to/css1" type="text/css" media="all" rel="stylesheet" /> 88 <link href="http://media.example.com/path/to/css2" type="text/css" media="all" rel="stylesheet" /> 89 <script type="text/javascript" src="http://media.example.com/path/to/js1"></script> 90 <script type="text/javascript" src="http://media.other.com/path/to/js2"></script> 91 <script type="text/javascript" src="https://secure.other.com/path/to/js3"></script> 92 93 # If a widget extends another but defines media, it overrides the parent widget's media. 94 >>> class MyWidget5(MyWidget1): 95 ... class Media: 96 ... css = { 97 ... 'all': ('/path/to/css3','/path/to/css1') 98 ... } 99 ... js = ('/path/to/js1','/path/to/js4') 100 101 >>> w5 = MyWidget5() 102 >>> print w5.media 103 <link href="http://media.example.com/path/to/css3" type="text/css" media="all" rel="stylesheet" /> 104 <link href="http://media.example.com/path/to/css1" type="text/css" media="all" rel="stylesheet" /> 105 <script type="text/javascript" src="http://media.example.com/path/to/js1"></script> 106 <script type="text/javascript" src="http://media.example.com/path/to/js4"></script> 107 108 # You can ask a form for the media required by its widgets. 109 >>> class MyForm(Form): 110 ... field1 = CharField(max_length=20, widget=MyWidget1()) 111 ... field2 = CharField(max_length=20, widget=MyWidget2()) 112 >>> f1 = MyForm() 113 >>> print f1.media 114 <link href="http://media.example.com/path/to/css1" type="text/css" media="all" rel="stylesheet" /> 115 <link href="http://media.example.com/path/to/css2" type="text/css" media="all" rel="stylesheet" /> 116 <link href="http://media.example.com/path/to/css3" type="text/css" media="all" rel="stylesheet" /> 117 <script type="text/javascript" src="http://media.example.com/path/to/js1"></script> 118 <script type="text/javascript" src="http://media.other.com/path/to/js2"></script> 119 <script type="text/javascript" src="https://secure.other.com/path/to/js3"></script> 120 <script type="text/javascript" src="http://media.example.com/path/to/js4"></script> 121 122 # Form media can be combined to produce a single media definition. 123 >>> class AnotherForm(Form): 124 ... field3 = CharField(max_length=20, widget=MyWidget3()) 125 >>> f2 = AnotherForm() 126 >>> print f1.media + f2.media 127 <link href="http://media.example.com/path/to/css1" type="text/css" media="all" rel="stylesheet" /> 128 <link href="http://media.example.com/path/to/css2" type="text/css" media="all" rel="stylesheet" /> 129 <link href="http://media.example.com/path/to/css3" type="text/css" media="all" rel="stylesheet" /> 130 <script type="text/javascript" src="http://media.example.com/path/to/js1"></script> 131 <script type="text/javascript" src="http://media.other.com/path/to/js2"></script> 132 <script type="text/javascript" src="https://secure.other.com/path/to/js3"></script> 133 <script type="text/javascript" src="http://media.example.com/path/to/js4"></script> 134 135 # Form media can be defined as a property, too 136 >>> class MyWidget6(TextInput): 137 ... def _media(self): 138 ... return Media(css={'all': ('/some/path',)}) 139 ... media = property(_media) 140 141 >>> w6 = MyWidget6() 142 >>> print w6.media 143 <link href="http://media.example.com/some/path" type="text/css" media="all" rel="stylesheet" /> 144 145 # You can extend media, if required. 146 >>> class MyWidget7(MyWidget6): 147 ... def _media(self): 148 ... return super(MyWidget7, self).media + Media(css={'all': ('/other/path',)}) 149 ... media = property(_media) 150 151 >>> w7 = MyWidget7() 152 >>> print w7.media 153 <link href="http://media.example.com/some/path" type="text/css" media="all" rel="stylesheet" /> 154 <link href="http://media.example.com/other/path" type="text/css" media="all" rel="stylesheet" /> 155 156 # A widget can define CSS media for multiple output media types 157 >>> class MyWidget8(TextInput): 158 ... class Media: 159 ... css = { 160 ... 'screen, print': ('/file1','/file2'), 161 ... 'screen': ('/file3',), 162 ... 'print': ('/file4',) 163 ... } 164 ... js = ('/path/to/js1','/path/to/js4') 165 166 >>> w8 = MyWidget8() 167 >>> print w8.media 168 <link href="http://media.example.com/file4" type="text/css" media="print" rel="stylesheet" /> 169 <link href="http://media.example.com/file3" type="text/css" media="screen" rel="stylesheet" /> 170 <link href="http://media.example.com/file1" type="text/css" media="screen, print" rel="stylesheet" /> 171 <link href="http://media.example.com/file2" type="text/css" media="screen, print" rel="stylesheet" /> 172 <script type="text/javascript" src="http://media.example.com/path/to/js1"></script> 173 <script type="text/javascript" src="http://media.example.com/path/to/js4"></script> 174 175 # MultiWidgets have a default media definition that gets all the 176 # media from the component widgets 177 >>> class MyWidget9(MultiWidget): 178 ... def __init__(self, attrs=None): 179 ... widgets = [MyWidget1, MyWidget2, MyWidget3] 180 ... MultiWidget.__init__(self, widgets, attrs) 181 182 >>> w9 = MyWidget9() 183 >>> print w9.media 184 <link href="http://media.example.com/path/to/css1" type="text/css" media="all" rel="stylesheet" /> 185 <link href="http://media.example.com/path/to/css2" type="text/css" media="all" rel="stylesheet" /> 186 <link href="http://media.example.com/path/to/css3" type="text/css" media="all" rel="stylesheet" /> 187 <script type="text/javascript" src="http://media.example.com/path/to/js1"></script> 188 <script type="text/javascript" src="http://media.other.com/path/to/js2"></script> 189 <script type="text/javascript" src="https://secure.other.com/path/to/js3"></script> 190 <script type="text/javascript" src="http://media.example.com/path/to/js4"></script> 191 192 """ 193 No newline at end of file -
tests/regressiontests/forms/tests.py
2 2 from localflavor import localflavor_tests 3 3 from regressions import regression_tests 4 4 from formsets import formset_tests 5 from media import media_tests 5 6 6 7 form_tests = r""" 7 8 >>> from django.newforms import * … … 3698 3699 'localflavor': localflavor_tests, 3699 3700 'regressions': regression_tests, 3700 3701 'formset_tests': formset_tests, 3702 'media_tests': media_tests, 3701 3703 } 3702 3704 3703 3705 if __name__ == "__main__":