1
# -*- coding: utf-8 -*-
3
>>> from django.forms import *
4
>>> from django.utils.encoding import force_unicode
9
... from decimal import Decimal
10
... except ImportError:
11
... from django.utils._decimal import Decimal
17
The forms library comes with some extra, higher-level Field and Widget
18
classes that demonstrate some of the library's abilities.
20
# SelectDateWidget ############################################################
22
>>> from django.forms.extras import SelectDateWidget
23
>>> w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016'))
24
>>> print w.render('mydate', '')
25
<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
>>> w.render('mydate', None) == w.render('mydate', '')
89
>>> print w.render('mydate', '2010-04-15')
90
<select name="mydate_month" id="id_mydate_month">
91
<option value="1">January</option>
92
<option value="2">February</option>
93
<option value="3">March</option>
94
<option value="4" selected="selected">April</option>
95
<option value="5">May</option>
96
<option value="6">June</option>
97
<option value="7">July</option>
98
<option value="8">August</option>
99
<option value="9">September</option>
100
<option value="10">October</option>
101
<option value="11">November</option>
102
<option value="12">December</option>
104
<select name="mydate_day" id="id_mydate_day">
105
<option value="1">1</option>
106
<option value="2">2</option>
107
<option value="3">3</option>
108
<option value="4">4</option>
109
<option value="5">5</option>
110
<option value="6">6</option>
111
<option value="7">7</option>
112
<option value="8">8</option>
113
<option value="9">9</option>
114
<option value="10">10</option>
115
<option value="11">11</option>
116
<option value="12">12</option>
117
<option value="13">13</option>
118
<option value="14">14</option>
119
<option value="15" selected="selected">15</option>
120
<option value="16">16</option>
121
<option value="17">17</option>
122
<option value="18">18</option>
123
<option value="19">19</option>
124
<option value="20">20</option>
125
<option value="21">21</option>
126
<option value="22">22</option>
127
<option value="23">23</option>
128
<option value="24">24</option>
129
<option value="25">25</option>
130
<option value="26">26</option>
131
<option value="27">27</option>
132
<option value="28">28</option>
133
<option value="29">29</option>
134
<option value="30">30</option>
135
<option value="31">31</option>
137
<select name="mydate_year" id="id_mydate_year">
138
<option value="2007">2007</option>
139
<option value="2008">2008</option>
140
<option value="2009">2009</option>
141
<option value="2010" selected="selected">2010</option>
142
<option value="2011">2011</option>
143
<option value="2012">2012</option>
144
<option value="2013">2013</option>
145
<option value="2014">2014</option>
146
<option value="2015">2015</option>
147
<option value="2016">2016</option>
150
Accepts a datetime or a string:
152
>>> w.render('mydate', datetime.date(2010, 4, 15)) == w.render('mydate', '2010-04-15')
155
Invalid dates still render the failed date:
156
>>> print w.render('mydate', '2010-02-31')
157
<select name="mydate_month" id="id_mydate_month">
158
<option value="1">January</option>
159
<option value="2" selected="selected">February</option>
160
<option value="3">March</option>
161
<option value="4">April</option>
162
<option value="5">May</option>
163
<option value="6">June</option>
164
<option value="7">July</option>
165
<option value="8">August</option>
166
<option value="9">September</option>
167
<option value="10">October</option>
168
<option value="11">November</option>
169
<option value="12">December</option>
171
<select name="mydate_day" id="id_mydate_day">
172
<option value="1">1</option>
173
<option value="2">2</option>
174
<option value="3">3</option>
175
<option value="4">4</option>
176
<option value="5">5</option>
177
<option value="6">6</option>
178
<option value="7">7</option>
179
<option value="8">8</option>
180
<option value="9">9</option>
181
<option value="10">10</option>
182
<option value="11">11</option>
183
<option value="12">12</option>
184
<option value="13">13</option>
185
<option value="14">14</option>
186
<option value="15">15</option>
187
<option value="16">16</option>
188
<option value="17">17</option>
189
<option value="18">18</option>
190
<option value="19">19</option>
191
<option value="20">20</option>
192
<option value="21">21</option>
193
<option value="22">22</option>
194
<option value="23">23</option>
195
<option value="24">24</option>
196
<option value="25">25</option>
197
<option value="26">26</option>
198
<option value="27">27</option>
199
<option value="28">28</option>
200
<option value="29">29</option>
201
<option value="30">30</option>
202
<option value="31" selected="selected">31</option>
204
<select name="mydate_year" id="id_mydate_year">
205
<option value="2007">2007</option>
206
<option value="2008">2008</option>
207
<option value="2009">2009</option>
208
<option value="2010" selected="selected">2010</option>
209
<option value="2011">2011</option>
210
<option value="2012">2012</option>
211
<option value="2013">2013</option>
212
<option value="2014">2014</option>
213
<option value="2015">2015</option>
214
<option value="2016">2016</option>
217
Using a SelectDateWidget in a form:
219
>>> w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016'), required=False)
220
>>> print w.render('mydate', '')
221
<select name="mydate_month" id="id_mydate_month">
222
<option value="0">---</option>
223
<option value="1">January</option>
224
<option value="2">February</option>
225
<option value="3">March</option>
226
<option value="4">April</option>
227
<option value="5">May</option>
228
<option value="6">June</option>
229
<option value="7">July</option>
230
<option value="8">August</option>
231
<option value="9">September</option>
232
<option value="10">October</option>
233
<option value="11">November</option>
234
<option value="12">December</option>
236
<select name="mydate_day" id="id_mydate_day">
237
<option value="0">---</option>
238
<option value="1">1</option>
239
<option value="2">2</option>
240
<option value="3">3</option>
241
<option value="4">4</option>
242
<option value="5">5</option>
243
<option value="6">6</option>
244
<option value="7">7</option>
245
<option value="8">8</option>
246
<option value="9">9</option>
247
<option value="10">10</option>
248
<option value="11">11</option>
249
<option value="12">12</option>
250
<option value="13">13</option>
251
<option value="14">14</option>
252
<option value="15">15</option>
253
<option value="16">16</option>
254
<option value="17">17</option>
255
<option value="18">18</option>
256
<option value="19">19</option>
257
<option value="20">20</option>
258
<option value="21">21</option>
259
<option value="22">22</option>
260
<option value="23">23</option>
261
<option value="24">24</option>
262
<option value="25">25</option>
263
<option value="26">26</option>
264
<option value="27">27</option>
265
<option value="28">28</option>
266
<option value="29">29</option>
267
<option value="30">30</option>
268
<option value="31">31</option>
270
<select name="mydate_year" id="id_mydate_year">
271
<option value="0">---</option>
272
<option value="2007">2007</option>
273
<option value="2008">2008</option>
274
<option value="2009">2009</option>
275
<option value="2010">2010</option>
276
<option value="2011">2011</option>
277
<option value="2012">2012</option>
278
<option value="2013">2013</option>
279
<option value="2014">2014</option>
280
<option value="2015">2015</option>
281
<option value="2016">2016</option>
283
>>> print w.render('mydate', '2010-04-15')
284
<select name="mydate_month" id="id_mydate_month">
285
<option value="0">---</option>
286
<option value="1">January</option>
287
<option value="2">February</option>
288
<option value="3">March</option>
289
<option value="4" selected="selected">April</option>
290
<option value="5">May</option>
291
<option value="6">June</option>
292
<option value="7">July</option>
293
<option value="8">August</option>
294
<option value="9">September</option>
295
<option value="10">October</option>
296
<option value="11">November</option>
297
<option value="12">December</option>
299
<select name="mydate_day" id="id_mydate_day">
300
<option value="0">---</option>
301
<option value="1">1</option>
302
<option value="2">2</option>
303
<option value="3">3</option>
304
<option value="4">4</option>
305
<option value="5">5</option>
306
<option value="6">6</option>
307
<option value="7">7</option>
308
<option value="8">8</option>
309
<option value="9">9</option>
310
<option value="10">10</option>
311
<option value="11">11</option>
312
<option value="12">12</option>
313
<option value="13">13</option>
314
<option value="14">14</option>
315
<option value="15" selected="selected">15</option>
316
<option value="16">16</option>
317
<option value="17">17</option>
318
<option value="18">18</option>
319
<option value="19">19</option>
320
<option value="20">20</option>
321
<option value="21">21</option>
322
<option value="22">22</option>
323
<option value="23">23</option>
324
<option value="24">24</option>
325
<option value="25">25</option>
326
<option value="26">26</option>
327
<option value="27">27</option>
328
<option value="28">28</option>
329
<option value="29">29</option>
330
<option value="30">30</option>
331
<option value="31">31</option>
333
<select name="mydate_year" id="id_mydate_year">
334
<option value="0">---</option>
335
<option value="2007">2007</option>
336
<option value="2008">2008</option>
337
<option value="2009">2009</option>
338
<option value="2010" selected="selected">2010</option>
339
<option value="2011">2011</option>
340
<option value="2012">2012</option>
341
<option value="2013">2013</option>
342
<option value="2014">2014</option>
343
<option value="2015">2015</option>
344
<option value="2016">2016</option>
346
>>> class GetDate(Form):
347
... mydate = DateField(widget=SelectDateWidget)
348
>>> a = GetDate({'mydate_month':'4', 'mydate_day':'1', 'mydate_year':'2008'})
349
>>> print a.is_valid()
351
>>> print a.cleaned_data['mydate']
354
As with any widget that implements get_value_from_datadict,
355
we must be prepared to accept the input from the "as_hidden"
358
>>> print a['mydate'].as_hidden()
359
<input type="hidden" name="mydate" value="2008-4-1" id="id_mydate" />
360
>>> b=GetDate({'mydate':'2008-4-1'})
361
>>> print b.is_valid()
363
>>> print b.cleaned_data['mydate']
367
# MultiWidget and MultiValueField #############################################
368
# MultiWidgets are widgets composed of other widgets. They are usually
369
# combined with MultiValueFields - a field that is composed of other fields.
370
# MulitWidgets can themselved be composed of other MultiWidgets.
371
# SplitDateTimeWidget is one example of a MultiWidget.
373
>>> class ComplexMultiWidget(MultiWidget):
374
... def __init__(self, attrs=None):
377
... SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
378
... SplitDateTimeWidget(),
380
... super(ComplexMultiWidget, self).__init__(widgets, attrs)
382
... def decompress(self, value):
384
... data = value.split(',')
385
... return [data[0], data[1], datetime.datetime(*time.strptime(data[2], "%Y-%m-%d %H:%M:%S")[0:6])]
386
... return [None, None, None]
387
... def format_output(self, rendered_widgets):
388
... return u'\n'.join(rendered_widgets)
389
>>> w = ComplexMultiWidget()
390
>>> print w.render('name', 'some text,JP,2007-04-25 06:24:00')
391
<input type="text" name="name_0" value="some text" />
392
<select multiple="multiple" name="name_1">
393
<option value="J" selected="selected">John</option>
394
<option value="P" selected="selected">Paul</option>
395
<option value="G">George</option>
396
<option value="R">Ringo</option>
398
<input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" />
400
>>> class ComplexField(MultiValueField):
401
... def __init__(self, required=True, widget=None, label=None, initial=None):
404
... MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
405
... SplitDateTimeField()
407
... super(ComplexField, self).__init__(fields, required, widget, label, initial)
409
... def compress(self, data_list):
411
... return '%s,%s,%s' % (data_list[0],''.join(data_list[1]),data_list[2])
414
>>> f = ComplexField(widget=w)
415
>>> f.clean(['some text', ['J','P'], ['2007-04-25','6:24:00']])
416
u'some text,JP,2007-04-25 06:24:00'
417
>>> f.clean(['some text',['X'], ['2007-04-25','6:24:00']])
418
Traceback (most recent call last):
420
ValidationError: [u'Select a valid choice. X is not one of the available choices.']
422
# If insufficient data is provided, None is substituted
423
>>> f.clean(['some text',['JP']])
424
Traceback (most recent call last):
426
ValidationError: [u'This field is required.']
428
>>> class ComplexFieldForm(Form):
429
... field1 = ComplexField(widget=w)
430
>>> f = ComplexFieldForm()
432
<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" id="id_field1_0" />
433
<select multiple="multiple" name="field1_1" id="id_field1_1">
434
<option value="J">John</option>
435
<option value="P">Paul</option>
436
<option value="G">George</option>
437
<option value="R">Ringo</option>
439
<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>
441
>>> f = ComplexFieldForm({'field1_0':'some text','field1_1':['J','P'], 'field1_2_0':'2007-04-25', 'field1_2_1':'06:24:00'})
443
<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" value="some text" id="id_field1_0" />
444
<select multiple="multiple" name="field1_1" id="id_field1_1">
445
<option value="J" selected="selected">John</option>
446
<option value="P" selected="selected">Paul</option>
447
<option value="G">George</option>
448
<option value="R">Ringo</option>
450
<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>
452
>>> f.cleaned_data['field1']
453
u'some text,JP,2007-04-25 06:24:00'
456
# IPAddressField ##################################################################
458
>>> f = IPAddressField()
460
Traceback (most recent call last):
462
ValidationError: [u'This field is required.']
464
Traceback (most recent call last):
466
ValidationError: [u'This field is required.']
467
>>> f.clean('127.0.0.1')
470
Traceback (most recent call last):
472
ValidationError: [u'Enter a valid IPv4 address.']
473
>>> f.clean('127.0.0.')
474
Traceback (most recent call last):
476
ValidationError: [u'Enter a valid IPv4 address.']
477
>>> f.clean('1.2.3.4.5')
478
Traceback (most recent call last):
480
ValidationError: [u'Enter a valid IPv4 address.']
481
>>> f.clean('256.125.1.5')
482
Traceback (most recent call last):
484
ValidationError: [u'Enter a valid IPv4 address.']
486
>>> f = IPAddressField(required=False)
491
>>> f.clean('127.0.0.1')
494
Traceback (most recent call last):
496
ValidationError: [u'Enter a valid IPv4 address.']
497
>>> f.clean('127.0.0.')
498
Traceback (most recent call last):
500
ValidationError: [u'Enter a valid IPv4 address.']
501
>>> f.clean('1.2.3.4.5')
502
Traceback (most recent call last):
504
ValidationError: [u'Enter a valid IPv4 address.']
505
>>> f.clean('256.125.1.5')
506
Traceback (most recent call last):
508
ValidationError: [u'Enter a valid IPv4 address.']
510
#################################
511
# Tests of underlying functions #
512
#################################
514
# smart_unicode tests
515
>>> from django.utils.encoding import smart_unicode
517
... def __str__(self):
518
... return 'ŠĐĆŽćžšđ'
520
... def __str__(self):
522
... def __unicode__(self):
523
... return u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
524
>>> smart_unicode(Test())
525
u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
526
>>> smart_unicode(TestU())
527
u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
530
>>> smart_unicode('foo')
534
####################################
535
# Test accessing errors in clean() #
536
####################################
538
>>> class UserForm(Form):
539
... username = CharField(max_length=10)
540
... password = CharField(widget=PasswordInput)
542
... data = self.cleaned_data
543
... if not self.errors:
544
... data['username'] = data['username'].lower()
547
>>> f = UserForm({'username': 'SirRobin', 'password': 'blue'})
550
>>> f.cleaned_data['username']
553
#######################################
554
# Test overriding ErrorList in a form #
555
#######################################
557
>>> from django.forms.util import ErrorList
558
>>> class DivErrorList(ErrorList):
559
... def __unicode__(self):
560
... return self.as_divs()
561
... def as_divs(self):
562
... if not self: return u''
563
... return u'<div class="errorlist">%s</div>' % ''.join([u'<div class="error">%s</div>' % force_unicode(e) for e in self])
564
>>> class CommentForm(Form):
565
... name = CharField(max_length=50, required=False)
566
... email = EmailField()
567
... comment = CharField()
568
>>> data = dict(email='invalid')
569
>>> f = CommentForm(data, auto_id=False, error_class=DivErrorList)
571
<p>Name: <input type="text" name="name" maxlength="50" /></p>
572
<div class="errorlist"><div class="error">Enter a valid e-mail address.</div></div>
573
<p>Email: <input type="text" name="email" value="invalid" /></p>
574
<div class="errorlist"><div class="error">This field is required.</div></div>
575
<p>Comment: <input type="text" name="comment" /></p>
577
#################################
578
# Test multipart-encoded form #
579
#################################
581
>>> class FormWithoutFile(Form):
582
... username = CharField()
583
>>> class FormWithFile(Form):
584
... username = CharField()
585
... file = FileField()
586
>>> class FormWithImage(Form):
587
... image = ImageField()
589
>>> FormWithoutFile().is_multipart()
591
>>> FormWithFile().is_multipart()
593
>>> FormWithImage().is_multipart()