1
# -*- coding: utf-8 -*-
5
from django.conf import settings
6
from django.forms import *
7
from django.forms.extras import SelectDateWidget
8
from django.forms.util import ErrorList
9
from django.utils import translation
10
from django.utils.encoding import force_unicode
11
from django.utils.encoding import smart_unicode
12
from error_messages import AssertFormErrorsMixin
15
mydate = DateField(widget=SelectDateWidget)
17
class FormsExtraTestCase(unittest.TestCase, AssertFormErrorsMixin):
22
# The forms library comes with some extra, higher-level Field and Widget
23
def test_selectdate(self):
24
w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016'))
25
self.assertEqual(w.render('mydate', ''), """<select name="mydate_month" id="id_mydate_month">
26
<option value="0">---</option>
27
<option value="1">January</option>
28
<option value="2">February</option>
29
<option value="3">March</option>
30
<option value="4">April</option>
31
<option value="5">May</option>
32
<option value="6">June</option>
33
<option value="7">July</option>
34
<option value="8">August</option>
35
<option value="9">September</option>
36
<option value="10">October</option>
37
<option value="11">November</option>
38
<option value="12">December</option>
40
<select name="mydate_day" id="id_mydate_day">
41
<option value="0">---</option>
42
<option value="1">1</option>
43
<option value="2">2</option>
44
<option value="3">3</option>
45
<option value="4">4</option>
46
<option value="5">5</option>
47
<option value="6">6</option>
48
<option value="7">7</option>
49
<option value="8">8</option>
50
<option value="9">9</option>
51
<option value="10">10</option>
52
<option value="11">11</option>
53
<option value="12">12</option>
54
<option value="13">13</option>
55
<option value="14">14</option>
56
<option value="15">15</option>
57
<option value="16">16</option>
58
<option value="17">17</option>
59
<option value="18">18</option>
60
<option value="19">19</option>
61
<option value="20">20</option>
62
<option value="21">21</option>
63
<option value="22">22</option>
64
<option value="23">23</option>
65
<option value="24">24</option>
66
<option value="25">25</option>
67
<option value="26">26</option>
68
<option value="27">27</option>
69
<option value="28">28</option>
70
<option value="29">29</option>
71
<option value="30">30</option>
72
<option value="31">31</option>
74
<select name="mydate_year" id="id_mydate_year">
75
<option value="0">---</option>
76
<option value="2007">2007</option>
77
<option value="2008">2008</option>
78
<option value="2009">2009</option>
79
<option value="2010">2010</option>
80
<option value="2011">2011</option>
81
<option value="2012">2012</option>
82
<option value="2013">2013</option>
83
<option value="2014">2014</option>
84
<option value="2015">2015</option>
85
<option value="2016">2016</option>
87
self.assertEqual(w.render('mydate', None), w.render('mydate', ''))
89
self.assertEqual(w.render('mydate', '2010-04-15'), """<select name="mydate_month" id="id_mydate_month">
90
<option value="1">January</option>
91
<option value="2">February</option>
92
<option value="3">March</option>
93
<option value="4" selected="selected">April</option>
94
<option value="5">May</option>
95
<option value="6">June</option>
96
<option value="7">July</option>
97
<option value="8">August</option>
98
<option value="9">September</option>
99
<option value="10">October</option>
100
<option value="11">November</option>
101
<option value="12">December</option>
103
<select name="mydate_day" id="id_mydate_day">
104
<option value="1">1</option>
105
<option value="2">2</option>
106
<option value="3">3</option>
107
<option value="4">4</option>
108
<option value="5">5</option>
109
<option value="6">6</option>
110
<option value="7">7</option>
111
<option value="8">8</option>
112
<option value="9">9</option>
113
<option value="10">10</option>
114
<option value="11">11</option>
115
<option value="12">12</option>
116
<option value="13">13</option>
117
<option value="14">14</option>
118
<option value="15" selected="selected">15</option>
119
<option value="16">16</option>
120
<option value="17">17</option>
121
<option value="18">18</option>
122
<option value="19">19</option>
123
<option value="20">20</option>
124
<option value="21">21</option>
125
<option value="22">22</option>
126
<option value="23">23</option>
127
<option value="24">24</option>
128
<option value="25">25</option>
129
<option value="26">26</option>
130
<option value="27">27</option>
131
<option value="28">28</option>
132
<option value="29">29</option>
133
<option value="30">30</option>
134
<option value="31">31</option>
136
<select name="mydate_year" id="id_mydate_year">
137
<option value="2007">2007</option>
138
<option value="2008">2008</option>
139
<option value="2009">2009</option>
140
<option value="2010" selected="selected">2010</option>
141
<option value="2011">2011</option>
142
<option value="2012">2012</option>
143
<option value="2013">2013</option>
144
<option value="2014">2014</option>
145
<option value="2015">2015</option>
146
<option value="2016">2016</option>
149
# Accepts a datetime or a string:
150
self.assertEqual(w.render('mydate', datetime.date(2010, 4, 15)), w.render('mydate', '2010-04-15'))
152
# Invalid dates still render the failed date:
153
self.assertEqual(w.render('mydate', '2010-02-31'), """<select name="mydate_month" id="id_mydate_month">
154
<option value="1">January</option>
155
<option value="2" selected="selected">February</option>
156
<option value="3">March</option>
157
<option value="4">April</option>
158
<option value="5">May</option>
159
<option value="6">June</option>
160
<option value="7">July</option>
161
<option value="8">August</option>
162
<option value="9">September</option>
163
<option value="10">October</option>
164
<option value="11">November</option>
165
<option value="12">December</option>
167
<select name="mydate_day" id="id_mydate_day">
168
<option value="1">1</option>
169
<option value="2">2</option>
170
<option value="3">3</option>
171
<option value="4">4</option>
172
<option value="5">5</option>
173
<option value="6">6</option>
174
<option value="7">7</option>
175
<option value="8">8</option>
176
<option value="9">9</option>
177
<option value="10">10</option>
178
<option value="11">11</option>
179
<option value="12">12</option>
180
<option value="13">13</option>
181
<option value="14">14</option>
182
<option value="15">15</option>
183
<option value="16">16</option>
184
<option value="17">17</option>
185
<option value="18">18</option>
186
<option value="19">19</option>
187
<option value="20">20</option>
188
<option value="21">21</option>
189
<option value="22">22</option>
190
<option value="23">23</option>
191
<option value="24">24</option>
192
<option value="25">25</option>
193
<option value="26">26</option>
194
<option value="27">27</option>
195
<option value="28">28</option>
196
<option value="29">29</option>
197
<option value="30">30</option>
198
<option value="31" selected="selected">31</option>
200
<select name="mydate_year" id="id_mydate_year">
201
<option value="2007">2007</option>
202
<option value="2008">2008</option>
203
<option value="2009">2009</option>
204
<option value="2010" selected="selected">2010</option>
205
<option value="2011">2011</option>
206
<option value="2012">2012</option>
207
<option value="2013">2013</option>
208
<option value="2014">2014</option>
209
<option value="2015">2015</option>
210
<option value="2016">2016</option>
213
# Using a SelectDateWidget in a form:
214
w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016'), required=False)
215
self.assertEqual(w.render('mydate', ''), """<select name="mydate_month" id="id_mydate_month">
216
<option value="0">---</option>
217
<option value="1">January</option>
218
<option value="2">February</option>
219
<option value="3">March</option>
220
<option value="4">April</option>
221
<option value="5">May</option>
222
<option value="6">June</option>
223
<option value="7">July</option>
224
<option value="8">August</option>
225
<option value="9">September</option>
226
<option value="10">October</option>
227
<option value="11">November</option>
228
<option value="12">December</option>
230
<select name="mydate_day" id="id_mydate_day">
231
<option value="0">---</option>
232
<option value="1">1</option>
233
<option value="2">2</option>
234
<option value="3">3</option>
235
<option value="4">4</option>
236
<option value="5">5</option>
237
<option value="6">6</option>
238
<option value="7">7</option>
239
<option value="8">8</option>
240
<option value="9">9</option>
241
<option value="10">10</option>
242
<option value="11">11</option>
243
<option value="12">12</option>
244
<option value="13">13</option>
245
<option value="14">14</option>
246
<option value="15">15</option>
247
<option value="16">16</option>
248
<option value="17">17</option>
249
<option value="18">18</option>
250
<option value="19">19</option>
251
<option value="20">20</option>
252
<option value="21">21</option>
253
<option value="22">22</option>
254
<option value="23">23</option>
255
<option value="24">24</option>
256
<option value="25">25</option>
257
<option value="26">26</option>
258
<option value="27">27</option>
259
<option value="28">28</option>
260
<option value="29">29</option>
261
<option value="30">30</option>
262
<option value="31">31</option>
264
<select name="mydate_year" id="id_mydate_year">
265
<option value="0">---</option>
266
<option value="2007">2007</option>
267
<option value="2008">2008</option>
268
<option value="2009">2009</option>
269
<option value="2010">2010</option>
270
<option value="2011">2011</option>
271
<option value="2012">2012</option>
272
<option value="2013">2013</option>
273
<option value="2014">2014</option>
274
<option value="2015">2015</option>
275
<option value="2016">2016</option>
277
self.assertEqual(w.render('mydate', '2010-04-15'), """<select name="mydate_month" id="id_mydate_month">
278
<option value="0">---</option>
279
<option value="1">January</option>
280
<option value="2">February</option>
281
<option value="3">March</option>
282
<option value="4" selected="selected">April</option>
283
<option value="5">May</option>
284
<option value="6">June</option>
285
<option value="7">July</option>
286
<option value="8">August</option>
287
<option value="9">September</option>
288
<option value="10">October</option>
289
<option value="11">November</option>
290
<option value="12">December</option>
292
<select name="mydate_day" id="id_mydate_day">
293
<option value="0">---</option>
294
<option value="1">1</option>
295
<option value="2">2</option>
296
<option value="3">3</option>
297
<option value="4">4</option>
298
<option value="5">5</option>
299
<option value="6">6</option>
300
<option value="7">7</option>
301
<option value="8">8</option>
302
<option value="9">9</option>
303
<option value="10">10</option>
304
<option value="11">11</option>
305
<option value="12">12</option>
306
<option value="13">13</option>
307
<option value="14">14</option>
308
<option value="15" selected="selected">15</option>
309
<option value="16">16</option>
310
<option value="17">17</option>
311
<option value="18">18</option>
312
<option value="19">19</option>
313
<option value="20">20</option>
314
<option value="21">21</option>
315
<option value="22">22</option>
316
<option value="23">23</option>
317
<option value="24">24</option>
318
<option value="25">25</option>
319
<option value="26">26</option>
320
<option value="27">27</option>
321
<option value="28">28</option>
322
<option value="29">29</option>
323
<option value="30">30</option>
324
<option value="31">31</option>
326
<select name="mydate_year" id="id_mydate_year">
327
<option value="0">---</option>
328
<option value="2007">2007</option>
329
<option value="2008">2008</option>
330
<option value="2009">2009</option>
331
<option value="2010" selected="selected">2010</option>
332
<option value="2011">2011</option>
333
<option value="2012">2012</option>
334
<option value="2013">2013</option>
335
<option value="2014">2014</option>
336
<option value="2015">2015</option>
337
<option value="2016">2016</option>
340
a = GetDate({'mydate_month':'4', 'mydate_day':'1', 'mydate_year':'2008'})
341
self.assertTrue(a.is_valid())
342
self.assertEqual(a.cleaned_data['mydate'], datetime.date(2008, 4, 1))
344
# As with any widget that implements get_value_from_datadict,
345
# we must be prepared to accept the input from the "as_hidden"
348
self.assertEqual(a['mydate'].as_hidden(), '<input type="hidden" name="mydate" value="2008-4-1" id="id_mydate" />')
350
b = GetDate({'mydate':'2008-4-1'})
351
self.assertTrue(b.is_valid())
352
self.assertEqual(b.cleaned_data['mydate'], datetime.date(2008, 4, 1))
354
# Invalid dates shouldn't be allowed
355
c = GetDate({'mydate_month':'2', 'mydate_day':'31', 'mydate_year':'2010'})
356
self.assertFalse(c.is_valid())
357
self.assertEqual(c.errors, {'mydate': [u'Enter a valid date.']})
359
# label tag is correctly associated with month dropdown
360
d = GetDate({'mydate_month':'1', 'mydate_day':'1', 'mydate_year':'2010'})
361
self.assertTrue('<label for="id_mydate_month">' in d.as_p())
363
def test_multiwidget(self):
364
# MultiWidget and MultiValueField #############################################
365
# MultiWidgets are widgets composed of other widgets. They are usually
366
# combined with MultiValueFields - a field that is composed of other fields.
367
# MulitWidgets can themselved be composed of other MultiWidgets.
368
# SplitDateTimeWidget is one example of a MultiWidget.
370
class ComplexMultiWidget(MultiWidget):
371
def __init__(self, attrs=None):
374
SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
375
SplitDateTimeWidget(),
377
super(ComplexMultiWidget, self).__init__(widgets, attrs)
379
def decompress(self, value):
381
data = value.split(',')
382
return [data[0], data[1], datetime.datetime(*time.strptime(data[2], "%Y-%m-%d %H:%M:%S")[0:6])]
383
return [None, None, None]
385
def format_output(self, rendered_widgets):
386
return u'\n'.join(rendered_widgets)
388
w = ComplexMultiWidget()
389
self.assertEqual(w.render('name', 'some text,JP,2007-04-25 06:24:00'), """<input type="text" name="name_0" value="some text" />
390
<select multiple="multiple" name="name_1">
391
<option value="J" selected="selected">John</option>
392
<option value="P" selected="selected">Paul</option>
393
<option value="G">George</option>
394
<option value="R">Ringo</option>
396
<input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" />""")
398
class ComplexField(MultiValueField):
399
def __init__(self, required=True, widget=None, label=None, initial=None):
402
MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
405
super(ComplexField, self).__init__(fields, required, widget, label, initial)
407
def compress(self, data_list):
409
return '%s,%s,%s' % (data_list[0],''.join(data_list[1]),data_list[2])
412
f = ComplexField(widget=w)
413
self.assertEqual(f.clean(['some text', ['J','P'], ['2007-04-25','6:24:00']]), u'some text,JP,2007-04-25 06:24:00')
414
self.assertFormErrors([u'Select a valid choice. X is not one of the available choices.'], f.clean, ['some text',['X'], ['2007-04-25','6:24:00']])
416
# If insufficient data is provided, None is substituted
417
self.assertFormErrors([u'This field is required.'], f.clean, ['some text',['JP']])
419
class ComplexFieldForm(Form):
420
field1 = ComplexField(widget=w)
422
f = ComplexFieldForm()
423
self.assertEqual(f.as_table(), """<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" id="id_field1_0" />
424
<select multiple="multiple" name="field1_1" id="id_field1_1">
425
<option value="J">John</option>
426
<option value="P">Paul</option>
427
<option value="G">George</option>
428
<option value="R">Ringo</option>
430
<input type="text" name="field1_2_0" id="id_field1_2_0" /><input type="text" name="field1_2_1" id="id_field1_2_1" /></td></tr>""")
432
f = ComplexFieldForm({'field1_0':'some text','field1_1':['J','P'], 'field1_2_0':'2007-04-25', 'field1_2_1':'06:24:00'})
433
self.assertEqual(f.as_table(), """<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" value="some text" id="id_field1_0" />
434
<select multiple="multiple" name="field1_1" id="id_field1_1">
435
<option value="J" selected="selected">John</option>
436
<option value="P" selected="selected">Paul</option>
437
<option value="G">George</option>
438
<option value="R">Ringo</option>
440
<input type="text" name="field1_2_0" value="2007-04-25" id="id_field1_2_0" /><input type="text" name="field1_2_1" value="06:24:00" id="id_field1_2_1" /></td></tr>""")
442
self.assertEqual(f.cleaned_data['field1'], u'some text,JP,2007-04-25 06:24:00')
444
def test_ipaddress(self):
446
self.assertFormErrors([u'This field is required.'], f.clean, '')
447
self.assertFormErrors([u'This field is required.'], f.clean, None)
448
self.assertEqual(f.clean('127.0.0.1'), u'127.0.0.1')
449
self.assertFormErrors([u'Enter a valid IPv4 address.'], f.clean, 'foo')
450
self.assertFormErrors([u'Enter a valid IPv4 address.'], f.clean, '127.0.0.')
451
self.assertFormErrors([u'Enter a valid IPv4 address.'], f.clean, '1.2.3.4.5')
452
self.assertFormErrors([u'Enter a valid IPv4 address.'], f.clean, '256.125.1.5')
454
f = IPAddressField(required=False)
455
self.assertEqual(f.clean(''), u'')
456
self.assertEqual(f.clean(None), u'')
457
self.assertEqual(f.clean('127.0.0.1'), u'127.0.0.1')
458
self.assertFormErrors([u'Enter a valid IPv4 address.'], f.clean, 'foo')
459
self.assertFormErrors([u'Enter a valid IPv4 address.'], f.clean, '127.0.0.')
460
self.assertFormErrors([u'Enter a valid IPv4 address.'], f.clean, '1.2.3.4.5')
461
self.assertFormErrors([u'Enter a valid IPv4 address.'], f.clean, '256.125.1.5')
463
def test_smart_unicode(self):
471
def __unicode__(self):
472
return u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
474
self.assertEqual(smart_unicode(Test()), u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111')
475
self.assertEqual(smart_unicode(TestU()), u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111')
476
self.assertEqual(smart_unicode(1), u'1')
477
self.assertEqual(smart_unicode('foo'), u'foo')
479
def test_accessing_clean(self):
480
class UserForm(Form):
481
username = CharField(max_length=10)
482
password = CharField(widget=PasswordInput)
485
data = self.cleaned_data
488
data['username'] = data['username'].lower()
492
f = UserForm({'username': 'SirRobin', 'password': 'blue'})
493
self.assertTrue(f.is_valid())
494
self.assertEqual(f.cleaned_data['username'], u'sirrobin')
496
def test_overriding_errorlist(self):
497
class DivErrorList(ErrorList):
498
def __unicode__(self):
499
return self.as_divs()
502
if not self: return u''
503
return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % force_unicode(e) for e in self])
505
class CommentForm(Form):
506
name = CharField(max_length=50, required=False)
508
comment = CharField()
510
data = dict(email='invalid')
511
f = CommentForm(data, auto_id=False, error_class=DivErrorList)
512
self.assertEqual(f.as_p(), """<p>Name: <input type="text" name="name" maxlength="50" /></p>
513
<div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div>
514
<p>Email: <input type="text" name="email" value="invalid" /></p>
515
<div class="errorlist"><div class="error">This field is required.</div></div>
516
<p>Comment: <input type="text" name="comment" /></p>""")
518
def test_multipart_encoded_form(self):
519
class FormWithoutFile(Form):
520
username = CharField()
522
class FormWithFile(Form):
523
username = CharField()
526
class FormWithImage(Form):
529
self.assertFalse(FormWithoutFile().is_multipart())
530
self.assertTrue(FormWithFile().is_multipart())
531
self.assertTrue(FormWithImage().is_multipart())
534
class FormsExtraL10NTestCase(unittest.TestCase):
536
super(FormsExtraL10NTestCase, self).setUp()
537
self.old_use_l10n = getattr(settings, 'USE_L10N', False)
538
settings.USE_L10N = True
539
translation.activate('nl')
542
translation.deactivate()
543
settings.USE_L10N = self.old_use_l10n
544
super(FormsExtraL10NTestCase, self).tearDown()
547
w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016'), required=False)
548
self.assertEqual(w.value_from_datadict({'date_year': '2010', 'date_month': '8', 'date_day': '13'}, {}, 'date'), '13-08-2010')
550
self.assertEqual(w.render('date', '13-08-2010'), """<select name="date_day" id="id_date_day">
551
<option value="0">---</option>
552
<option value="1">1</option>
553
<option value="2">2</option>
554
<option value="3">3</option>
555
<option value="4">4</option>
556
<option value="5">5</option>
557
<option value="6">6</option>
558
<option value="7">7</option>
559
<option value="8">8</option>
560
<option value="9">9</option>
561
<option value="10">10</option>
562
<option value="11">11</option>
563
<option value="12">12</option>
564
<option value="13" selected="selected">13</option>
565
<option value="14">14</option>
566
<option value="15">15</option>
567
<option value="16">16</option>
568
<option value="17">17</option>
569
<option value="18">18</option>
570
<option value="19">19</option>
571
<option value="20">20</option>
572
<option value="21">21</option>
573
<option value="22">22</option>
574
<option value="23">23</option>
575
<option value="24">24</option>
576
<option value="25">25</option>
577
<option value="26">26</option>
578
<option value="27">27</option>
579
<option value="28">28</option>
580
<option value="29">29</option>
581
<option value="30">30</option>
582
<option value="31">31</option>
584
<select name="date_month" id="id_date_month">
585
<option value="0">---</option>
586
<option value="1">januari</option>
587
<option value="2">februari</option>
588
<option value="3">maart</option>
589
<option value="4">april</option>
590
<option value="5">mei</option>
591
<option value="6">juni</option>
592
<option value="7">juli</option>
593
<option value="8" selected="selected">augustus</option>
594
<option value="9">september</option>
595
<option value="10">oktober</option>
596
<option value="11">november</option>
597
<option value="12">december</option>
599
<select name="date_year" id="id_date_year">
600
<option value="0">---</option>
601
<option value="2007">2007</option>
602
<option value="2008">2008</option>
603
<option value="2009">2009</option>
604
<option value="2010" selected="selected">2010</option>
605
<option value="2011">2011</option>
606
<option value="2012">2012</option>
607
<option value="2013">2013</option>
608
<option value="2014">2014</option>
609
<option value="2015">2015</option>
610
<option value="2016">2016</option>
613
# Years before 1900 work
614
w = SelectDateWidget(years=('1899',))
615
self.assertEqual(w.value_from_datadict({'date_year': '1899', 'date_month': '8', 'date_day': '13'}, {}, 'date'), '13-08-1899')
617
def test_l10n_invalid_date_in(self):
618
# Invalid dates shouldn't be allowed
619
a = GetDate({'mydate_month':'2', 'mydate_day':'31', 'mydate_year':'2010'})
620
self.assertFalse(a.is_valid())
621
# 'Geef een geldige datum op.' = 'Enter a valid date.'
622
self.assertEqual(a.errors, {'mydate': [u'Geef een geldige datum op.']})
624
def test_form_label_association(self):
625
# label tag is correctly associated with first rendered dropdown
626
a = GetDate({'mydate_month':'1', 'mydate_day':'1', 'mydate_year':'2010'})
627
self.assertTrue('<label for="id_mydate_day">' in a.as_p())