1
# -*- coding: utf-8 -*-
2
from django.forms import TextInput, Media, TextInput, CharField, Form, MultiWidget
3
from django.template import Template, Context
4
from django.test import TestCase
5
from django.test.utils import override_settings
10
MEDIA_URL='http://media.example.com/media/',
12
class FormsMediaTestCase(TestCase):
13
"""Tests for the media handling on widgets and forms"""
15
def test_construction(self):
16
# Check construction of media objects
17
m = Media(css={'all': ('path/to/css1','/path/to/css2')}, js=('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3'))
18
self.assertEqual(str(m), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
19
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
20
<script type="text/javascript" src="/path/to/js1"></script>
21
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
22
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
26
'all': ('path/to/css1','/path/to/css2')
28
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
31
self.assertEqual(str(m3), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
32
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
33
<script type="text/javascript" src="/path/to/js1"></script>
34
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
35
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
37
# A widget can exist without a media definition
38
class MyWidget(TextInput):
42
self.assertEqual(str(w.media), '')
44
def test_media_dsl(self):
45
###############################################################
46
# DSL Class-based media definitions
47
###############################################################
49
# A widget can define media if it needs to.
50
# Any absolute path will be preserved; relative paths are combined
51
# with the value of settings.MEDIA_URL
52
class MyWidget1(TextInput):
55
'all': ('path/to/css1','/path/to/css2')
57
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
60
self.assertEqual(str(w1.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
61
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
62
<script type="text/javascript" src="/path/to/js1"></script>
63
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
64
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
66
# Media objects can be interrogated by media type
67
self.assertEqual(str(w1.media['css']), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
68
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />""")
70
self.assertEqual(str(w1.media['js']), """<script type="text/javascript" src="/path/to/js1"></script>
71
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
72
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
74
def test_combine_media(self):
75
# Media objects can be combined. Any given media resource will appear only
76
# once. Duplicated media definitions are ignored.
77
class MyWidget1(TextInput):
80
'all': ('path/to/css1','/path/to/css2')
82
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
84
class MyWidget2(TextInput):
87
'all': ('/path/to/css2','/path/to/css3')
89
js = ('/path/to/js1','/path/to/js4')
91
class MyWidget3(TextInput):
94
'all': ('/path/to/css3','path/to/css1')
96
js = ('/path/to/js1','/path/to/js4')
101
self.assertEqual(str(w1.media + w2.media + w3.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
102
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
103
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
104
<script type="text/javascript" src="/path/to/js1"></script>
105
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
106
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
107
<script type="text/javascript" src="/path/to/js4"></script>""")
109
# Check that media addition hasn't affected the original objects
110
self.assertEqual(str(w1.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
111
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
112
<script type="text/javascript" src="/path/to/js1"></script>
113
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
114
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
116
# Regression check for #12879: specifying the same CSS or JS file
117
# multiple times in a single Media instance should result in that file
118
# only being included once.
119
class MyWidget4(TextInput):
121
css = {'all': ('/path/to/css1', '/path/to/css1')}
122
js = ('/path/to/js1', '/path/to/js1')
125
self.assertEqual(str(w4.media), """<link href="/path/to/css1" type="text/css" media="all" rel="stylesheet" />
126
<script type="text/javascript" src="/path/to/js1"></script>""")
128
def test_media_property(self):
129
###############################################################
130
# Property-based media definitions
131
###############################################################
133
# Widget media can be defined as a property
134
class MyWidget4(TextInput):
136
return Media(css={'all': ('/some/path',)}, js = ('/some/js',))
137
media = property(_media)
140
self.assertEqual(str(w4.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
141
<script type="text/javascript" src="/some/js"></script>""")
143
# Media properties can reference the media of their parents
144
class MyWidget5(MyWidget4):
146
return super(MyWidget5, self).media + Media(css={'all': ('/other/path',)}, js = ('/other/js',))
147
media = property(_media)
150
self.assertEqual(str(w5.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
151
<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
152
<script type="text/javascript" src="/some/js"></script>
153
<script type="text/javascript" src="/other/js"></script>""")
155
def test_media_property_parent_references(self):
156
# Media properties can reference the media of their parents,
157
# even if the parent media was defined using a class
158
class MyWidget1(TextInput):
161
'all': ('path/to/css1','/path/to/css2')
163
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
165
class MyWidget6(MyWidget1):
167
return super(MyWidget6, self).media + Media(css={'all': ('/other/path',)}, js = ('/other/js',))
168
media = property(_media)
171
self.assertEqual(str(w6.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
172
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
173
<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
174
<script type="text/javascript" src="/path/to/js1"></script>
175
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
176
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
177
<script type="text/javascript" src="/other/js"></script>""")
179
def test_media_inheritance(self):
180
###############################################################
181
# Inheritance of media
182
###############################################################
184
# If a widget extends another but provides no media definition, it inherits the parent widget's media
185
class MyWidget1(TextInput):
188
'all': ('path/to/css1','/path/to/css2')
190
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
192
class MyWidget7(MyWidget1):
196
self.assertEqual(str(w7.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
197
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
198
<script type="text/javascript" src="/path/to/js1"></script>
199
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
200
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
202
# If a widget extends another but defines media, it extends the parent widget's media by default
203
class MyWidget8(MyWidget1):
206
'all': ('/path/to/css3','path/to/css1')
208
js = ('/path/to/js1','/path/to/js4')
211
self.assertEqual(str(w8.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
212
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
213
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
214
<script type="text/javascript" src="/path/to/js1"></script>
215
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
216
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
217
<script type="text/javascript" src="/path/to/js4"></script>""")
219
def test_media_inheritance_from_property(self):
220
# If a widget extends another but defines media, it extends the parents widget's media,
221
# even if the parent defined media using a property.
222
class MyWidget1(TextInput):
225
'all': ('path/to/css1','/path/to/css2')
227
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
229
class MyWidget4(TextInput):
231
return Media(css={'all': ('/some/path',)}, js = ('/some/js',))
232
media = property(_media)
234
class MyWidget9(MyWidget4):
237
'all': ('/other/path',)
242
self.assertEqual(str(w9.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
243
<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
244
<script type="text/javascript" src="/some/js"></script>
245
<script type="text/javascript" src="/other/js"></script>""")
247
# A widget can disable media inheritance by specifying 'extend=False'
248
class MyWidget10(MyWidget1):
252
'all': ('/path/to/css3','path/to/css1')
254
js = ('/path/to/js1','/path/to/js4')
257
self.assertEqual(str(w10.media), """<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
258
<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
259
<script type="text/javascript" src="/path/to/js1"></script>
260
<script type="text/javascript" src="/path/to/js4"></script>""")
262
def test_media_inheritance_extends(self):
263
# A widget can explicitly enable full media inheritance by specifying 'extend=True'
264
class MyWidget1(TextInput):
267
'all': ('path/to/css1','/path/to/css2')
269
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
271
class MyWidget11(MyWidget1):
275
'all': ('/path/to/css3','path/to/css1')
277
js = ('/path/to/js1','/path/to/js4')
280
self.assertEqual(str(w11.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
281
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
282
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
283
<script type="text/javascript" src="/path/to/js1"></script>
284
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
285
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
286
<script type="text/javascript" src="/path/to/js4"></script>""")
288
def test_media_inheritance_single_type(self):
289
# A widget can enable inheritance of one media type by specifying extend as a tuple
290
class MyWidget1(TextInput):
293
'all': ('path/to/css1','/path/to/css2')
295
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
297
class MyWidget12(MyWidget1):
301
'all': ('/path/to/css3','path/to/css1')
303
js = ('/path/to/js1','/path/to/js4')
306
self.assertEqual(str(w12.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
307
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
308
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
309
<script type="text/javascript" src="/path/to/js1"></script>
310
<script type="text/javascript" src="/path/to/js4"></script>""")
312
def test_multi_media(self):
313
###############################################################
314
# Multi-media handling for CSS
315
###############################################################
317
# A widget can define CSS media for multiple output media types
318
class MultimediaWidget(TextInput):
321
'screen, print': ('/file1','/file2'),
322
'screen': ('/file3',),
325
js = ('/path/to/js1','/path/to/js4')
327
multimedia = MultimediaWidget()
328
self.assertEqual(str(multimedia.media), """<link href="/file4" type="text/css" media="print" rel="stylesheet" />
329
<link href="/file3" type="text/css" media="screen" rel="stylesheet" />
330
<link href="/file1" type="text/css" media="screen, print" rel="stylesheet" />
331
<link href="/file2" type="text/css" media="screen, print" rel="stylesheet" />
332
<script type="text/javascript" src="/path/to/js1"></script>
333
<script type="text/javascript" src="/path/to/js4"></script>""")
335
def test_multi_widget(self):
336
###############################################################
337
# Multiwidget media handling
338
###############################################################
340
class MyWidget1(TextInput):
343
'all': ('path/to/css1','/path/to/css2')
345
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
347
class MyWidget2(TextInput):
350
'all': ('/path/to/css2','/path/to/css3')
352
js = ('/path/to/js1','/path/to/js4')
354
class MyWidget3(TextInput):
357
'all': ('/path/to/css3','path/to/css1')
359
js = ('/path/to/js1','/path/to/js4')
361
# MultiWidgets have a default media definition that gets all the
362
# media from the component widgets
363
class MyMultiWidget(MultiWidget):
364
def __init__(self, attrs=None):
365
widgets = [MyWidget1, MyWidget2, MyWidget3]
366
super(MyMultiWidget, self).__init__(widgets, attrs)
368
mymulti = MyMultiWidget()
369
self.assertEqual(str(mymulti.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
370
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
371
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
372
<script type="text/javascript" src="/path/to/js1"></script>
373
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
374
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
375
<script type="text/javascript" src="/path/to/js4"></script>""")
377
def test_form_media(self):
378
###############################################################
379
# Media processing for forms
380
###############################################################
382
class MyWidget1(TextInput):
385
'all': ('path/to/css1','/path/to/css2')
387
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
389
class MyWidget2(TextInput):
392
'all': ('/path/to/css2','/path/to/css3')
394
js = ('/path/to/js1','/path/to/js4')
396
class MyWidget3(TextInput):
399
'all': ('/path/to/css3','path/to/css1')
401
js = ('/path/to/js1','/path/to/js4')
403
# You can ask a form for the media required by its widgets.
405
field1 = CharField(max_length=20, widget=MyWidget1())
406
field2 = CharField(max_length=20, widget=MyWidget2())
408
self.assertEqual(str(f1.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
409
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
410
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
411
<script type="text/javascript" src="/path/to/js1"></script>
412
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
413
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
414
<script type="text/javascript" src="/path/to/js4"></script>""")
416
# Form media can be combined to produce a single media definition.
417
class AnotherForm(Form):
418
field3 = CharField(max_length=20, widget=MyWidget3())
420
self.assertEqual(str(f1.media + f2.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
421
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
422
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
423
<script type="text/javascript" src="/path/to/js1"></script>
424
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
425
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
426
<script type="text/javascript" src="/path/to/js4"></script>""")
428
# Forms can also define media, following the same rules as widgets.
429
class FormWithMedia(Form):
430
field1 = CharField(max_length=20, widget=MyWidget1())
431
field2 = CharField(max_length=20, widget=MyWidget2())
433
js = ('/some/form/javascript',)
435
'all': ('/some/form/css',)
438
self.assertEqual(str(f3.media), """<link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
439
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
440
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
441
<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />
442
<script type="text/javascript" src="/path/to/js1"></script>
443
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
444
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
445
<script type="text/javascript" src="/path/to/js4"></script>
446
<script type="text/javascript" src="/some/form/javascript"></script>""")
448
# Media works in templates
449
self.assertEqual(Template("{{ form.media.js }}{{ form.media.css }}").render(Context({'form': f3})), """<script type="text/javascript" src="/path/to/js1"></script>
450
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
451
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
452
<script type="text/javascript" src="/path/to/js4"></script>
453
<script type="text/javascript" src="/some/form/javascript"></script><link href="http://media.example.com/media/path/to/css1" type="text/css" media="all" rel="stylesheet" />
454
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
455
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
456
<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />""")
460
STATIC_URL='http://media.example.com/static/',
461
MEDIA_URL='http://media.example.com/media/',
463
class StaticFormsMediaTestCase(TestCase):
464
"""Tests for the media handling on widgets and forms"""
466
def test_construction(self):
467
# Check construction of media objects
468
m = Media(css={'all': ('path/to/css1','/path/to/css2')}, js=('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3'))
469
self.assertEqual(str(m), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
470
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
471
<script type="text/javascript" src="/path/to/js1"></script>
472
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
473
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
477
'all': ('path/to/css1','/path/to/css2')
479
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
482
self.assertEqual(str(m3), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
483
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
484
<script type="text/javascript" src="/path/to/js1"></script>
485
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
486
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
488
# A widget can exist without a media definition
489
class MyWidget(TextInput):
493
self.assertEqual(str(w.media), '')
495
def test_media_dsl(self):
496
###############################################################
497
# DSL Class-based media definitions
498
###############################################################
500
# A widget can define media if it needs to.
501
# Any absolute path will be preserved; relative paths are combined
502
# with the value of settings.MEDIA_URL
503
class MyWidget1(TextInput):
506
'all': ('path/to/css1','/path/to/css2')
508
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
511
self.assertEqual(str(w1.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
512
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
513
<script type="text/javascript" src="/path/to/js1"></script>
514
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
515
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
517
# Media objects can be interrogated by media type
518
self.assertEqual(str(w1.media['css']), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
519
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />""")
521
self.assertEqual(str(w1.media['js']), """<script type="text/javascript" src="/path/to/js1"></script>
522
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
523
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
525
def test_combine_media(self):
526
# Media objects can be combined. Any given media resource will appear only
527
# once. Duplicated media definitions are ignored.
528
class MyWidget1(TextInput):
531
'all': ('path/to/css1','/path/to/css2')
533
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
535
class MyWidget2(TextInput):
538
'all': ('/path/to/css2','/path/to/css3')
540
js = ('/path/to/js1','/path/to/js4')
542
class MyWidget3(TextInput):
545
'all': ('/path/to/css3','path/to/css1')
547
js = ('/path/to/js1','/path/to/js4')
552
self.assertEqual(str(w1.media + w2.media + w3.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
553
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
554
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
555
<script type="text/javascript" src="/path/to/js1"></script>
556
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
557
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
558
<script type="text/javascript" src="/path/to/js4"></script>""")
560
# Check that media addition hasn't affected the original objects
561
self.assertEqual(str(w1.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
562
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
563
<script type="text/javascript" src="/path/to/js1"></script>
564
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
565
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
567
# Regression check for #12879: specifying the same CSS or JS file
568
# multiple times in a single Media instance should result in that file
569
# only being included once.
570
class MyWidget4(TextInput):
572
css = {'all': ('/path/to/css1', '/path/to/css1')}
573
js = ('/path/to/js1', '/path/to/js1')
576
self.assertEqual(str(w4.media), """<link href="/path/to/css1" type="text/css" media="all" rel="stylesheet" />
577
<script type="text/javascript" src="/path/to/js1"></script>""")
579
def test_media_property(self):
580
###############################################################
581
# Property-based media definitions
582
###############################################################
584
# Widget media can be defined as a property
585
class MyWidget4(TextInput):
587
return Media(css={'all': ('/some/path',)}, js = ('/some/js',))
588
media = property(_media)
591
self.assertEqual(str(w4.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
592
<script type="text/javascript" src="/some/js"></script>""")
594
# Media properties can reference the media of their parents
595
class MyWidget5(MyWidget4):
597
return super(MyWidget5, self).media + Media(css={'all': ('/other/path',)}, js = ('/other/js',))
598
media = property(_media)
601
self.assertEqual(str(w5.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
602
<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
603
<script type="text/javascript" src="/some/js"></script>
604
<script type="text/javascript" src="/other/js"></script>""")
606
def test_media_property_parent_references(self):
607
# Media properties can reference the media of their parents,
608
# even if the parent media was defined using a class
609
class MyWidget1(TextInput):
612
'all': ('path/to/css1','/path/to/css2')
614
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
616
class MyWidget6(MyWidget1):
618
return super(MyWidget6, self).media + Media(css={'all': ('/other/path',)}, js = ('/other/js',))
619
media = property(_media)
622
self.assertEqual(str(w6.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
623
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
624
<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
625
<script type="text/javascript" src="/path/to/js1"></script>
626
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
627
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
628
<script type="text/javascript" src="/other/js"></script>""")
630
def test_media_inheritance(self):
631
###############################################################
632
# Inheritance of media
633
###############################################################
635
# If a widget extends another but provides no media definition, it inherits the parent widget's media
636
class MyWidget1(TextInput):
639
'all': ('path/to/css1','/path/to/css2')
641
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
643
class MyWidget7(MyWidget1):
647
self.assertEqual(str(w7.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
648
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
649
<script type="text/javascript" src="/path/to/js1"></script>
650
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
651
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>""")
653
# If a widget extends another but defines media, it extends the parent widget's media by default
654
class MyWidget8(MyWidget1):
657
'all': ('/path/to/css3','path/to/css1')
659
js = ('/path/to/js1','/path/to/js4')
662
self.assertEqual(str(w8.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
663
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
664
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
665
<script type="text/javascript" src="/path/to/js1"></script>
666
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
667
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
668
<script type="text/javascript" src="/path/to/js4"></script>""")
670
def test_media_inheritance_from_property(self):
671
# If a widget extends another but defines media, it extends the parents widget's media,
672
# even if the parent defined media using a property.
673
class MyWidget1(TextInput):
676
'all': ('path/to/css1','/path/to/css2')
678
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
680
class MyWidget4(TextInput):
682
return Media(css={'all': ('/some/path',)}, js = ('/some/js',))
683
media = property(_media)
685
class MyWidget9(MyWidget4):
688
'all': ('/other/path',)
693
self.assertEqual(str(w9.media), """<link href="/some/path" type="text/css" media="all" rel="stylesheet" />
694
<link href="/other/path" type="text/css" media="all" rel="stylesheet" />
695
<script type="text/javascript" src="/some/js"></script>
696
<script type="text/javascript" src="/other/js"></script>""")
698
# A widget can disable media inheritance by specifying 'extend=False'
699
class MyWidget10(MyWidget1):
703
'all': ('/path/to/css3','path/to/css1')
705
js = ('/path/to/js1','/path/to/js4')
708
self.assertEqual(str(w10.media), """<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
709
<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
710
<script type="text/javascript" src="/path/to/js1"></script>
711
<script type="text/javascript" src="/path/to/js4"></script>""")
713
def test_media_inheritance_extends(self):
714
# A widget can explicitly enable full media inheritance by specifying 'extend=True'
715
class MyWidget1(TextInput):
718
'all': ('path/to/css1','/path/to/css2')
720
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
722
class MyWidget11(MyWidget1):
726
'all': ('/path/to/css3','path/to/css1')
728
js = ('/path/to/js1','/path/to/js4')
731
self.assertEqual(str(w11.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
732
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
733
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
734
<script type="text/javascript" src="/path/to/js1"></script>
735
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
736
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
737
<script type="text/javascript" src="/path/to/js4"></script>""")
739
def test_media_inheritance_single_type(self):
740
# A widget can enable inheritance of one media type by specifying extend as a tuple
741
class MyWidget1(TextInput):
744
'all': ('path/to/css1','/path/to/css2')
746
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
748
class MyWidget12(MyWidget1):
752
'all': ('/path/to/css3','path/to/css1')
754
js = ('/path/to/js1','/path/to/js4')
757
self.assertEqual(str(w12.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
758
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
759
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
760
<script type="text/javascript" src="/path/to/js1"></script>
761
<script type="text/javascript" src="/path/to/js4"></script>""")
763
def test_multi_media(self):
764
###############################################################
765
# Multi-media handling for CSS
766
###############################################################
768
# A widget can define CSS media for multiple output media types
769
class MultimediaWidget(TextInput):
772
'screen, print': ('/file1','/file2'),
773
'screen': ('/file3',),
776
js = ('/path/to/js1','/path/to/js4')
778
multimedia = MultimediaWidget()
779
self.assertEqual(str(multimedia.media), """<link href="/file4" type="text/css" media="print" rel="stylesheet" />
780
<link href="/file3" type="text/css" media="screen" rel="stylesheet" />
781
<link href="/file1" type="text/css" media="screen, print" rel="stylesheet" />
782
<link href="/file2" type="text/css" media="screen, print" rel="stylesheet" />
783
<script type="text/javascript" src="/path/to/js1"></script>
784
<script type="text/javascript" src="/path/to/js4"></script>""")
786
def test_multi_widget(self):
787
###############################################################
788
# Multiwidget media handling
789
###############################################################
791
class MyWidget1(TextInput):
794
'all': ('path/to/css1','/path/to/css2')
796
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
798
class MyWidget2(TextInput):
801
'all': ('/path/to/css2','/path/to/css3')
803
js = ('/path/to/js1','/path/to/js4')
805
class MyWidget3(TextInput):
808
'all': ('/path/to/css3','path/to/css1')
810
js = ('/path/to/js1','/path/to/js4')
812
# MultiWidgets have a default media definition that gets all the
813
# media from the component widgets
814
class MyMultiWidget(MultiWidget):
815
def __init__(self, attrs=None):
816
widgets = [MyWidget1, MyWidget2, MyWidget3]
817
super(MyMultiWidget, self).__init__(widgets, attrs)
819
mymulti = MyMultiWidget()
820
self.assertEqual(str(mymulti.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
821
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
822
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
823
<script type="text/javascript" src="/path/to/js1"></script>
824
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
825
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
826
<script type="text/javascript" src="/path/to/js4"></script>""")
828
def test_form_media(self):
829
###############################################################
830
# Media processing for forms
831
###############################################################
833
class MyWidget1(TextInput):
836
'all': ('path/to/css1','/path/to/css2')
838
js = ('/path/to/js1','http://media.other.com/path/to/js2','https://secure.other.com/path/to/js3')
840
class MyWidget2(TextInput):
843
'all': ('/path/to/css2','/path/to/css3')
845
js = ('/path/to/js1','/path/to/js4')
847
class MyWidget3(TextInput):
850
'all': ('/path/to/css3','path/to/css1')
852
js = ('/path/to/js1','/path/to/js4')
854
# You can ask a form for the media required by its widgets.
856
field1 = CharField(max_length=20, widget=MyWidget1())
857
field2 = CharField(max_length=20, widget=MyWidget2())
859
self.assertEqual(str(f1.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
860
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
861
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
862
<script type="text/javascript" src="/path/to/js1"></script>
863
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
864
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
865
<script type="text/javascript" src="/path/to/js4"></script>""")
867
# Form media can be combined to produce a single media definition.
868
class AnotherForm(Form):
869
field3 = CharField(max_length=20, widget=MyWidget3())
871
self.assertEqual(str(f1.media + f2.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
872
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
873
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
874
<script type="text/javascript" src="/path/to/js1"></script>
875
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
876
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
877
<script type="text/javascript" src="/path/to/js4"></script>""")
879
# Forms can also define media, following the same rules as widgets.
880
class FormWithMedia(Form):
881
field1 = CharField(max_length=20, widget=MyWidget1())
882
field2 = CharField(max_length=20, widget=MyWidget2())
884
js = ('/some/form/javascript',)
886
'all': ('/some/form/css',)
889
self.assertEqual(str(f3.media), """<link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
890
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
891
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
892
<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />
893
<script type="text/javascript" src="/path/to/js1"></script>
894
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
895
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
896
<script type="text/javascript" src="/path/to/js4"></script>
897
<script type="text/javascript" src="/some/form/javascript"></script>""")
899
# Media works in templates
900
self.assertEqual(Template("{{ form.media.js }}{{ form.media.css }}").render(Context({'form': f3})), """<script type="text/javascript" src="/path/to/js1"></script>
901
<script type="text/javascript" src="http://media.other.com/path/to/js2"></script>
902
<script type="text/javascript" src="https://secure.other.com/path/to/js3"></script>
903
<script type="text/javascript" src="/path/to/js4"></script>
904
<script type="text/javascript" src="/some/form/javascript"></script><link href="http://media.example.com/static/path/to/css1" type="text/css" media="all" rel="stylesheet" />
905
<link href="/path/to/css2" type="text/css" media="all" rel="stylesheet" />
906
<link href="/path/to/css3" type="text/css" media="all" rel="stylesheet" />
907
<link href="/some/form/css" type="text/css" media="all" rel="stylesheet" />""")