1
1
# -*- coding: utf-8 -*-
2
from localflavor import localflavor_tests
3
from regressions import regression_tests
6
>>> from django.newforms import *
7
>>> from django.newforms.widgets import RadioFieldRenderer
12
... from decimal import Decimal
13
... except ImportError:
14
... from django.utils._decimal import Decimal
20
Each Widget class corresponds to an HTML form widget. A Widget knows how to
21
render itself, given a field name and some data. Widgets don't perform
24
# TextInput Widget ############################################################
27
>>> w.render('email', '')
28
u'<input type="text" name="email" />'
29
>>> w.render('email', None)
30
u'<input type="text" name="email" />'
31
>>> w.render('email', 'test@example.com')
32
u'<input type="text" name="email" value="test@example.com" />'
33
>>> w.render('email', 'some "quoted" & ampersanded value')
34
u'<input type="text" name="email" value="some "quoted" & ampersanded value" />'
35
>>> w.render('email', 'test@example.com', attrs={'class': 'fun'})
36
u'<input type="text" name="email" value="test@example.com" class="fun" />'
38
# Note that doctest in Python 2.4 (and maybe 2.5?) doesn't support non-ascii
39
# characters in output, so we're displaying the repr() here.
40
>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})
41
u'<input type="text" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" class="fun" />'
43
You can also pass 'attrs' to the constructor:
44
>>> w = TextInput(attrs={'class': 'fun'})
45
>>> w.render('email', '')
46
u'<input type="text" class="fun" name="email" />'
47
>>> w.render('email', 'foo@example.com')
48
u'<input type="text" class="fun" value="foo@example.com" name="email" />'
50
'attrs' passed to render() get precedence over those passed to the constructor:
51
>>> w = TextInput(attrs={'class': 'pretty'})
52
>>> w.render('email', '', attrs={'class': 'special'})
53
u'<input type="text" class="special" name="email" />'
55
# PasswordInput Widget ############################################################
57
>>> w = PasswordInput()
58
>>> w.render('email', '')
59
u'<input type="password" name="email" />'
60
>>> w.render('email', None)
61
u'<input type="password" name="email" />'
62
>>> w.render('email', 'test@example.com')
63
u'<input type="password" name="email" value="test@example.com" />'
64
>>> w.render('email', 'some "quoted" & ampersanded value')
65
u'<input type="password" name="email" value="some "quoted" & ampersanded value" />'
66
>>> w.render('email', 'test@example.com', attrs={'class': 'fun'})
67
u'<input type="password" name="email" value="test@example.com" class="fun" />'
69
You can also pass 'attrs' to the constructor:
70
>>> w = PasswordInput(attrs={'class': 'fun'})
71
>>> w.render('email', '')
72
u'<input type="password" class="fun" name="email" />'
73
>>> w.render('email', 'foo@example.com')
74
u'<input type="password" class="fun" value="foo@example.com" name="email" />'
76
'attrs' passed to render() get precedence over those passed to the constructor:
77
>>> w = PasswordInput(attrs={'class': 'pretty'})
78
>>> w.render('email', '', attrs={'class': 'special'})
79
u'<input type="password" class="special" name="email" />'
81
>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})
82
u'<input type="password" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />'
84
The render_value argument lets you specify whether the widget should render
85
its value. You may want to do this for security reasons.
86
>>> w = PasswordInput(render_value=True)
87
>>> w.render('email', 'secret')
88
u'<input type="password" name="email" value="secret" />'
89
>>> w = PasswordInput(render_value=False)
90
>>> w.render('email', '')
91
u'<input type="password" name="email" />'
92
>>> w.render('email', None)
93
u'<input type="password" name="email" />'
94
>>> w.render('email', 'secret')
95
u'<input type="password" name="email" />'
96
>>> w = PasswordInput(attrs={'class': 'fun'}, render_value=False)
97
>>> w.render('email', 'secret')
98
u'<input type="password" class="fun" name="email" />'
100
# HiddenInput Widget ############################################################
102
>>> w = HiddenInput()
103
>>> w.render('email', '')
104
u'<input type="hidden" name="email" />'
105
>>> w.render('email', None)
106
u'<input type="hidden" name="email" />'
107
>>> w.render('email', 'test@example.com')
108
u'<input type="hidden" name="email" value="test@example.com" />'
109
>>> w.render('email', 'some "quoted" & ampersanded value')
110
u'<input type="hidden" name="email" value="some "quoted" & ampersanded value" />'
111
>>> w.render('email', 'test@example.com', attrs={'class': 'fun'})
112
u'<input type="hidden" name="email" value="test@example.com" class="fun" />'
114
You can also pass 'attrs' to the constructor:
115
>>> w = HiddenInput(attrs={'class': 'fun'})
116
>>> w.render('email', '')
117
u'<input type="hidden" class="fun" name="email" />'
118
>>> w.render('email', 'foo@example.com')
119
u'<input type="hidden" class="fun" value="foo@example.com" name="email" />'
121
'attrs' passed to render() get precedence over those passed to the constructor:
122
>>> w = HiddenInput(attrs={'class': 'pretty'})
123
>>> w.render('email', '', attrs={'class': 'special'})
124
u'<input type="hidden" class="special" name="email" />'
126
>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})
127
u'<input type="hidden" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />'
129
'attrs' passed to render() get precedence over those passed to the constructor:
130
>>> w = HiddenInput(attrs={'class': 'pretty'})
131
>>> w.render('email', '', attrs={'class': 'special'})
132
u'<input type="hidden" class="special" name="email" />'
134
# MultipleHiddenInput Widget ##################################################
136
>>> w = MultipleHiddenInput()
137
>>> w.render('email', [])
139
>>> w.render('email', None)
141
>>> w.render('email', ['test@example.com'])
142
u'<input type="hidden" name="email" value="test@example.com" />'
143
>>> w.render('email', ['some "quoted" & ampersanded value'])
144
u'<input type="hidden" name="email" value="some "quoted" & ampersanded value" />'
145
>>> w.render('email', ['test@example.com', 'foo@example.com'])
146
u'<input type="hidden" name="email" value="test@example.com" />\n<input type="hidden" name="email" value="foo@example.com" />'
147
>>> w.render('email', ['test@example.com'], attrs={'class': 'fun'})
148
u'<input type="hidden" name="email" value="test@example.com" class="fun" />'
149
>>> w.render('email', ['test@example.com', 'foo@example.com'], attrs={'class': 'fun'})
150
u'<input type="hidden" name="email" value="test@example.com" class="fun" />\n<input type="hidden" name="email" value="foo@example.com" class="fun" />'
152
You can also pass 'attrs' to the constructor:
153
>>> w = MultipleHiddenInput(attrs={'class': 'fun'})
154
>>> w.render('email', [])
156
>>> w.render('email', ['foo@example.com'])
157
u'<input type="hidden" class="fun" value="foo@example.com" name="email" />'
158
>>> w.render('email', ['foo@example.com', 'test@example.com'])
159
u'<input type="hidden" class="fun" value="foo@example.com" name="email" />\n<input type="hidden" class="fun" value="test@example.com" name="email" />'
161
'attrs' passed to render() get precedence over those passed to the constructor:
162
>>> w = MultipleHiddenInput(attrs={'class': 'pretty'})
163
>>> w.render('email', ['foo@example.com'], attrs={'class': 'special'})
164
u'<input type="hidden" class="special" value="foo@example.com" name="email" />'
166
>>> w.render('email', ['ŠĐĆŽćžšđ'], attrs={'class': 'fun'})
167
u'<input type="hidden" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />'
169
'attrs' passed to render() get precedence over those passed to the constructor:
170
>>> w = MultipleHiddenInput(attrs={'class': 'pretty'})
171
>>> w.render('email', ['foo@example.com'], attrs={'class': 'special'})
172
u'<input type="hidden" class="special" value="foo@example.com" name="email" />'
174
# FileInput Widget ############################################################
176
FileInput widgets don't ever show the value, because the old value is of no use
177
if you are updating the form or if the provided file generated an error.
179
>>> w.render('email', '')
180
u'<input type="file" name="email" />'
181
>>> w.render('email', None)
182
u'<input type="file" name="email" />'
183
>>> w.render('email', 'test@example.com')
184
u'<input type="file" name="email" />'
185
>>> w.render('email', 'some "quoted" & ampersanded value')
186
u'<input type="file" name="email" />'
187
>>> w.render('email', 'test@example.com', attrs={'class': 'fun'})
188
u'<input type="file" name="email" class="fun" />'
190
You can also pass 'attrs' to the constructor:
191
>>> w = FileInput(attrs={'class': 'fun'})
192
>>> w.render('email', '')
193
u'<input type="file" class="fun" name="email" />'
194
>>> w.render('email', 'foo@example.com')
195
u'<input type="file" class="fun" name="email" />'
197
>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})
198
u'<input type="file" class="fun" name="email" />'
200
# Textarea Widget #############################################################
203
>>> w.render('msg', '')
204
u'<textarea rows="10" cols="40" name="msg"></textarea>'
205
>>> w.render('msg', None)
206
u'<textarea rows="10" cols="40" name="msg"></textarea>'
207
>>> w.render('msg', 'value')
208
u'<textarea rows="10" cols="40" name="msg">value</textarea>'
209
>>> w.render('msg', 'some "quoted" & ampersanded value')
210
u'<textarea rows="10" cols="40" name="msg">some "quoted" & ampersanded value</textarea>'
211
>>> w.render('msg', 'value', attrs={'class': 'pretty', 'rows': 20})
212
u'<textarea class="pretty" rows="20" cols="40" name="msg">value</textarea>'
214
You can also pass 'attrs' to the constructor:
215
>>> w = Textarea(attrs={'class': 'pretty'})
216
>>> w.render('msg', '')
217
u'<textarea rows="10" cols="40" name="msg" class="pretty"></textarea>'
218
>>> w.render('msg', 'example')
219
u'<textarea rows="10" cols="40" name="msg" class="pretty">example</textarea>'
221
'attrs' passed to render() get precedence over those passed to the constructor:
222
>>> w = Textarea(attrs={'class': 'pretty'})
223
>>> w.render('msg', '', attrs={'class': 'special'})
224
u'<textarea rows="10" cols="40" name="msg" class="special"></textarea>'
226
>>> w.render('msg', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})
227
u'<textarea rows="10" cols="40" name="msg" class="fun">\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</textarea>'
229
# CheckboxInput Widget ########################################################
231
>>> w = CheckboxInput()
232
>>> w.render('is_cool', '')
233
u'<input type="checkbox" name="is_cool" />'
234
>>> w.render('is_cool', None)
235
u'<input type="checkbox" name="is_cool" />'
236
>>> w.render('is_cool', False)
237
u'<input type="checkbox" name="is_cool" />'
238
>>> w.render('is_cool', True)
239
u'<input checked="checked" type="checkbox" name="is_cool" />'
241
Using any value that's not in ('', None, False, True) will check the checkbox
242
and set the 'value' attribute.
243
>>> w.render('is_cool', 'foo')
244
u'<input checked="checked" type="checkbox" name="is_cool" value="foo" />'
246
>>> w.render('is_cool', False, attrs={'class': 'pretty'})
247
u'<input type="checkbox" name="is_cool" class="pretty" />'
249
You can also pass 'attrs' to the constructor:
250
>>> w = CheckboxInput(attrs={'class': 'pretty'})
251
>>> w.render('is_cool', '')
252
u'<input type="checkbox" class="pretty" name="is_cool" />'
254
'attrs' passed to render() get precedence over those passed to the constructor:
255
>>> w = CheckboxInput(attrs={'class': 'pretty'})
256
>>> w.render('is_cool', '', attrs={'class': 'special'})
257
u'<input type="checkbox" class="special" name="is_cool" />'
259
You can pass 'check_test' to the constructor. This is a callable that takes the
260
value and returns True if the box should be checked.
261
>>> w = CheckboxInput(check_test=lambda value: value.startswith('hello'))
262
>>> w.render('greeting', '')
263
u'<input type="checkbox" name="greeting" />'
264
>>> w.render('greeting', 'hello')
265
u'<input checked="checked" type="checkbox" name="greeting" value="hello" />'
266
>>> w.render('greeting', 'hello there')
267
u'<input checked="checked" type="checkbox" name="greeting" value="hello there" />'
268
>>> w.render('greeting', 'hello & goodbye')
269
u'<input checked="checked" type="checkbox" name="greeting" value="hello & goodbye" />'
271
A subtlety: If the 'check_test' argument cannot handle a value and raises any
272
exception during its __call__, then the exception will be swallowed and the box
273
will not be checked. In this example, the 'check_test' assumes the value has a
274
startswith() method, which fails for the values True, False and None.
275
>>> w.render('greeting', True)
276
u'<input type="checkbox" name="greeting" />'
277
>>> w.render('greeting', False)
278
u'<input type="checkbox" name="greeting" />'
279
>>> w.render('greeting', None)
280
u'<input type="checkbox" name="greeting" />'
282
# Select Widget ###############################################################
285
>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
286
<select name="beatle">
287
<option value="J" selected="selected">John</option>
288
<option value="P">Paul</option>
289
<option value="G">George</option>
290
<option value="R">Ringo</option>
293
If the value is None, none of the options are selected:
294
>>> print w.render('beatle', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
295
<select name="beatle">
296
<option value="J">John</option>
297
<option value="P">Paul</option>
298
<option value="G">George</option>
299
<option value="R">Ringo</option>
302
If the value corresponds to a label (but not to an option value), none of the options are selected:
303
>>> print w.render('beatle', 'John', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
304
<select name="beatle">
305
<option value="J">John</option>
306
<option value="P">Paul</option>
307
<option value="G">George</option>
308
<option value="R">Ringo</option>
311
The value is compared to its str():
312
>>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')])
314
<option value="1">1</option>
315
<option value="2" selected="selected">2</option>
316
<option value="3">3</option>
318
>>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)])
320
<option value="1">1</option>
321
<option value="2" selected="selected">2</option>
322
<option value="3">3</option>
324
>>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)])
326
<option value="1">1</option>
327
<option value="2" selected="selected">2</option>
328
<option value="3">3</option>
331
The 'choices' argument can be any iterable:
332
>>> from itertools import chain
333
>>> def get_choices():
334
... for i in range(5):
336
>>> print w.render('num', 2, choices=get_choices())
338
<option value="0">0</option>
339
<option value="1">1</option>
340
<option value="2" selected="selected">2</option>
341
<option value="3">3</option>
342
<option value="4">4</option>
344
>>> things = ({'id': 1, 'name': 'And Boom'}, {'id': 2, 'name': 'One More Thing!'})
345
>>> class SomeForm(Form):
346
... somechoice = ChoiceField(choices=chain((('', '-'*9),), [(thing['id'], thing['name']) for thing in things]))
349
u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>'
351
u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="" selected="selected">---------</option>\n<option value="1">And Boom</option>\n<option value="2">One More Thing!</option>\n</select></td></tr>'
352
>>> f = SomeForm({'somechoice': 2})
354
u'<tr><th><label for="id_somechoice">Somechoice:</label></th><td><select name="somechoice" id="id_somechoice">\n<option value="">---------</option>\n<option value="1">And Boom</option>\n<option value="2" selected="selected">One More Thing!</option>\n</select></td></tr>'
356
You can also pass 'choices' to the constructor:
357
>>> w = Select(choices=[(1, 1), (2, 2), (3, 3)])
358
>>> print w.render('num', 2)
360
<option value="1">1</option>
361
<option value="2" selected="selected">2</option>
362
<option value="3">3</option>
365
If 'choices' is passed to both the constructor and render(), then they'll both be in the output:
366
>>> print w.render('num', 2, choices=[(4, 4), (5, 5)])
368
<option value="1">1</option>
369
<option value="2" selected="selected">2</option>
370
<option value="3">3</option>
371
<option value="4">4</option>
372
<option value="5">5</option>
375
>>> w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
376
u'<select name="email">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>'
378
If choices is passed to the constructor and is a generator, it can be iterated
379
over multiple times without getting consumed:
380
>>> w = Select(choices=get_choices())
381
>>> print w.render('num', 2)
383
<option value="0">0</option>
384
<option value="1">1</option>
385
<option value="2" selected="selected">2</option>
386
<option value="3">3</option>
387
<option value="4">4</option>
389
>>> print w.render('num', 3)
391
<option value="0">0</option>
392
<option value="1">1</option>
393
<option value="2">2</option>
394
<option value="3" selected="selected">3</option>
395
<option value="4">4</option>
398
# NullBooleanSelect Widget ####################################################
400
>>> w = NullBooleanSelect()
401
>>> print w.render('is_cool', True)
402
<select name="is_cool">
403
<option value="1">Unknown</option>
404
<option value="2" selected="selected">Yes</option>
405
<option value="3">No</option>
407
>>> print w.render('is_cool', False)
408
<select name="is_cool">
409
<option value="1">Unknown</option>
410
<option value="2">Yes</option>
411
<option value="3" selected="selected">No</option>
413
>>> print w.render('is_cool', None)
414
<select name="is_cool">
415
<option value="1" selected="selected">Unknown</option>
416
<option value="2">Yes</option>
417
<option value="3">No</option>
419
>>> print w.render('is_cool', '2')
420
<select name="is_cool">
421
<option value="1">Unknown</option>
422
<option value="2" selected="selected">Yes</option>
423
<option value="3">No</option>
425
>>> print w.render('is_cool', '3')
426
<select name="is_cool">
427
<option value="1">Unknown</option>
428
<option value="2">Yes</option>
429
<option value="3" selected="selected">No</option>
432
# SelectMultiple Widget #######################################################
434
>>> w = SelectMultiple()
435
>>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
436
<select multiple="multiple" name="beatles">
437
<option value="J" selected="selected">John</option>
438
<option value="P">Paul</option>
439
<option value="G">George</option>
440
<option value="R">Ringo</option>
442
>>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
443
<select multiple="multiple" name="beatles">
444
<option value="J" selected="selected">John</option>
445
<option value="P" selected="selected">Paul</option>
446
<option value="G">George</option>
447
<option value="R">Ringo</option>
449
>>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
450
<select multiple="multiple" name="beatles">
451
<option value="J" selected="selected">John</option>
452
<option value="P" selected="selected">Paul</option>
453
<option value="G">George</option>
454
<option value="R" selected="selected">Ringo</option>
457
If the value is None, none of the options are selected:
458
>>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
459
<select multiple="multiple" name="beatles">
460
<option value="J">John</option>
461
<option value="P">Paul</option>
462
<option value="G">George</option>
463
<option value="R">Ringo</option>
466
If the value corresponds to a label (but not to an option value), none of the options are selected:
467
>>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
468
<select multiple="multiple" name="beatles">
469
<option value="J">John</option>
470
<option value="P">Paul</option>
471
<option value="G">George</option>
472
<option value="R">Ringo</option>
475
If multiple values are given, but some of them are not valid, the valid ones are selected:
476
>>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
477
<select multiple="multiple" name="beatles">
478
<option value="J" selected="selected">John</option>
479
<option value="P">Paul</option>
480
<option value="G" selected="selected">George</option>
481
<option value="R">Ringo</option>
484
The value is compared to its str():
485
>>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')])
486
<select multiple="multiple" name="nums">
487
<option value="1">1</option>
488
<option value="2" selected="selected">2</option>
489
<option value="3">3</option>
491
>>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)])
492
<select multiple="multiple" name="nums">
493
<option value="1">1</option>
494
<option value="2" selected="selected">2</option>
495
<option value="3">3</option>
497
>>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)])
498
<select multiple="multiple" name="nums">
499
<option value="1">1</option>
500
<option value="2" selected="selected">2</option>
501
<option value="3">3</option>
504
The 'choices' argument can be any iterable:
505
>>> def get_choices():
506
... for i in range(5):
508
>>> print w.render('nums', [2], choices=get_choices())
509
<select multiple="multiple" name="nums">
510
<option value="0">0</option>
511
<option value="1">1</option>
512
<option value="2" selected="selected">2</option>
513
<option value="3">3</option>
514
<option value="4">4</option>
517
You can also pass 'choices' to the constructor:
518
>>> w = SelectMultiple(choices=[(1, 1), (2, 2), (3, 3)])
519
>>> print w.render('nums', [2])
520
<select multiple="multiple" name="nums">
521
<option value="1">1</option>
522
<option value="2" selected="selected">2</option>
523
<option value="3">3</option>
526
If 'choices' is passed to both the constructor and render(), then they'll both be in the output:
527
>>> print w.render('nums', [2], choices=[(4, 4), (5, 5)])
528
<select multiple="multiple" name="nums">
529
<option value="1">1</option>
530
<option value="2" selected="selected">2</option>
531
<option value="3">3</option>
532
<option value="4">4</option>
533
<option value="5">5</option>
536
>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
537
u'<select multiple="multiple" name="nums">\n<option value="1">1</option>\n<option value="2">2</option>\n<option value="3">3</option>\n<option value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" selected="selected">\u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</option>\n<option value="\u0107\u017e\u0161\u0111">abc\u0107\u017e\u0161\u0111</option>\n</select>'
539
# RadioSelect Widget ##########################################################
541
>>> w = RadioSelect()
542
>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
544
<li><label><input checked="checked" type="radio" name="beatle" value="J" /> John</label></li>
545
<li><label><input type="radio" name="beatle" value="P" /> Paul</label></li>
546
<li><label><input type="radio" name="beatle" value="G" /> George</label></li>
547
<li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li>
550
If the value is None, none of the options are checked:
551
>>> print w.render('beatle', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
553
<li><label><input type="radio" name="beatle" value="J" /> John</label></li>
554
<li><label><input type="radio" name="beatle" value="P" /> Paul</label></li>
555
<li><label><input type="radio" name="beatle" value="G" /> George</label></li>
556
<li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li>
559
If the value corresponds to a label (but not to an option value), none of the options are checked:
560
>>> print w.render('beatle', 'John', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
562
<li><label><input type="radio" name="beatle" value="J" /> John</label></li>
563
<li><label><input type="radio" name="beatle" value="P" /> Paul</label></li>
564
<li><label><input type="radio" name="beatle" value="G" /> George</label></li>
565
<li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li>
568
The value is compared to its str():
569
>>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')])
571
<li><label><input type="radio" name="num" value="1" /> 1</label></li>
572
<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li>
573
<li><label><input type="radio" name="num" value="3" /> 3</label></li>
575
>>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)])
577
<li><label><input type="radio" name="num" value="1" /> 1</label></li>
578
<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li>
579
<li><label><input type="radio" name="num" value="3" /> 3</label></li>
581
>>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)])
583
<li><label><input type="radio" name="num" value="1" /> 1</label></li>
584
<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li>
585
<li><label><input type="radio" name="num" value="3" /> 3</label></li>
588
The 'choices' argument can be any iterable:
589
>>> def get_choices():
590
... for i in range(5):
592
>>> print w.render('num', 2, choices=get_choices())
594
<li><label><input type="radio" name="num" value="0" /> 0</label></li>
595
<li><label><input type="radio" name="num" value="1" /> 1</label></li>
596
<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li>
597
<li><label><input type="radio" name="num" value="3" /> 3</label></li>
598
<li><label><input type="radio" name="num" value="4" /> 4</label></li>
601
You can also pass 'choices' to the constructor:
602
>>> w = RadioSelect(choices=[(1, 1), (2, 2), (3, 3)])
603
>>> print w.render('num', 2)
605
<li><label><input type="radio" name="num" value="1" /> 1</label></li>
606
<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li>
607
<li><label><input type="radio" name="num" value="3" /> 3</label></li>
610
If 'choices' is passed to both the constructor and render(), then they'll both be in the output:
611
>>> print w.render('num', 2, choices=[(4, 4), (5, 5)])
613
<li><label><input type="radio" name="num" value="1" /> 1</label></li>
614
<li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li>
615
<li><label><input type="radio" name="num" value="3" /> 3</label></li>
616
<li><label><input type="radio" name="num" value="4" /> 4</label></li>
617
<li><label><input type="radio" name="num" value="5" /> 5</label></li>
620
RadioSelect uses a RadioFieldRenderer to render the individual radio inputs.
621
You can manipulate that object directly to customize the way the RadioSelect
623
>>> w = RadioSelect()
624
>>> r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
627
<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label>
628
<label><input type="radio" name="beatle" value="P" /> Paul</label>
629
<label><input type="radio" name="beatle" value="G" /> George</label>
630
<label><input type="radio" name="beatle" value="R" /> Ringo</label>
632
... print '%s<br />' % inp
633
<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label><br />
634
<label><input type="radio" name="beatle" value="P" /> Paul</label><br />
635
<label><input type="radio" name="beatle" value="G" /> George</label><br />
636
<label><input type="radio" name="beatle" value="R" /> Ringo</label><br />
638
... print '<p>%s %s</p>' % (inp.tag(), inp.choice_label)
639
<p><input checked="checked" type="radio" name="beatle" value="J" /> John</p>
640
<p><input type="radio" name="beatle" value="P" /> Paul</p>
641
<p><input type="radio" name="beatle" value="G" /> George</p>
642
<p><input type="radio" name="beatle" value="R" /> Ringo</p>
644
... print '%s %s %s %s %s' % (inp.name, inp.value, inp.choice_value, inp.choice_label, inp.is_checked())
646
beatle J P Paul False
647
beatle J G George False
648
beatle J R Ringo False
650
You can create your own custom renderers for RadioSelect to use.
651
>>> class MyRenderer(RadioFieldRenderer):
652
... def render(self):
653
... return u'<br />\n'.join([unicode(choice) for choice in self])
654
>>> w = RadioSelect(renderer=MyRenderer)
655
>>> print w.render('beatle', 'G', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
656
<label><input type="radio" name="beatle" value="J" /> John</label><br />
657
<label><input type="radio" name="beatle" value="P" /> Paul</label><br />
658
<label><input checked="checked" type="radio" name="beatle" value="G" /> George</label><br />
659
<label><input type="radio" name="beatle" value="R" /> Ringo</label>
661
A RadioFieldRenderer object also allows index access to individual RadioInput
663
>>> w = RadioSelect()
664
>>> r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
666
<label><input type="radio" name="beatle" value="P" /> Paul</label>
668
<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label>
669
>>> r[0].is_checked()
671
>>> r[1].is_checked()
673
>>> r[1].name, r[1].value, r[1].choice_value, r[1].choice_label
674
('beatle', u'J', u'P', u'Paul')
676
Traceback (most recent call last):
678
IndexError: list index out of range
680
# Unicode choices are correctly rendered as HTML
681
>>> w = RadioSelect()
682
>>> unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]))
683
u'<ul>\n<li><label><input checked="checked" type="radio" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="radio" name="email" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>'
685
# Attributes provided at instantiation are passed to the constituent inputs
686
>>> w = RadioSelect(attrs={'id':'foo'})
687
>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
689
<li><label><input checked="checked" type="radio" id="foo_0" value="J" name="beatle" /> John</label></li>
690
<li><label><input type="radio" id="foo_1" value="P" name="beatle" /> Paul</label></li>
691
<li><label><input type="radio" id="foo_2" value="G" name="beatle" /> George</label></li>
692
<li><label><input type="radio" id="foo_3" value="R" name="beatle" /> Ringo</label></li>
695
# Attributes provided at render-time are passed to the constituent inputs
696
>>> w = RadioSelect()
697
>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')), attrs={'id':'bar'})
699
<li><label><input checked="checked" type="radio" id="bar_0" value="J" name="beatle" /> John</label></li>
700
<li><label><input type="radio" id="bar_1" value="P" name="beatle" /> Paul</label></li>
701
<li><label><input type="radio" id="bar_2" value="G" name="beatle" /> George</label></li>
702
<li><label><input type="radio" id="bar_3" value="R" name="beatle" /> Ringo</label></li>
705
# CheckboxSelectMultiple Widget ###############################################
707
>>> w = CheckboxSelectMultiple()
708
>>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
710
<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li>
711
<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li>
712
<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
713
<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li>
715
>>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
717
<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li>
718
<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li>
719
<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
720
<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li>
722
>>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
724
<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li>
725
<li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li>
726
<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
727
<li><label><input checked="checked" type="checkbox" name="beatles" value="R" /> Ringo</label></li>
730
If the value is None, none of the options are selected:
731
>>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
733
<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li>
734
<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li>
735
<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
736
<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li>
739
If the value corresponds to a label (but not to an option value), none of the options are selected:
740
>>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
742
<li><label><input type="checkbox" name="beatles" value="J" /> John</label></li>
743
<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li>
744
<li><label><input type="checkbox" name="beatles" value="G" /> George</label></li>
745
<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li>
748
If multiple values are given, but some of them are not valid, the valid ones are selected:
749
>>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
751
<li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li>
752
<li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li>
753
<li><label><input checked="checked" type="checkbox" name="beatles" value="G" /> George</label></li>
754
<li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li>
757
The value is compared to its str():
758
>>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')])
760
<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>
761
<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li>
762
<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>
764
>>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)])
766
<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>
767
<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li>
768
<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>
770
>>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)])
772
<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>
773
<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li>
774
<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>
777
The 'choices' argument can be any iterable:
778
>>> def get_choices():
779
... for i in range(5):
781
>>> print w.render('nums', [2], choices=get_choices())
783
<li><label><input type="checkbox" name="nums" value="0" /> 0</label></li>
784
<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>
785
<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li>
786
<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>
787
<li><label><input type="checkbox" name="nums" value="4" /> 4</label></li>
790
You can also pass 'choices' to the constructor:
791
>>> w = CheckboxSelectMultiple(choices=[(1, 1), (2, 2), (3, 3)])
792
>>> print w.render('nums', [2])
794
<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>
795
<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li>
796
<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>
799
If 'choices' is passed to both the constructor and render(), then they'll both be in the output:
800
>>> print w.render('nums', [2], choices=[(4, 4), (5, 5)])
802
<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>
803
<li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li>
804
<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>
805
<li><label><input type="checkbox" name="nums" value="4" /> 4</label></li>
806
<li><label><input type="checkbox" name="nums" value="5" /> 5</label></li>
809
>>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])
810
u'<ul>\n<li><label><input type="checkbox" name="nums" value="1" /> 1</label></li>\n<li><label><input type="checkbox" name="nums" value="2" /> 2</label></li>\n<li><label><input type="checkbox" name="nums" value="3" /> 3</label></li>\n<li><label><input checked="checked" type="checkbox" name="nums" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" /> \u0160\u0110abc\u0106\u017d\u0107\u017e\u0161\u0111</label></li>\n<li><label><input type="checkbox" name="nums" value="\u0107\u017e\u0161\u0111" /> abc\u0107\u017e\u0161\u0111</label></li>\n</ul>'
812
# MultiWidget #################################################################
814
>>> class MyMultiWidget(MultiWidget):
815
... def decompress(self, value):
817
... return value.split('__')
819
... def format_output(self, rendered_widgets):
820
... return u'<br />'.join(rendered_widgets)
821
>>> w = MyMultiWidget(widgets=(TextInput(attrs={'class': 'big'}), TextInput(attrs={'class': 'small'})))
822
>>> w.render('name', ['john', 'lennon'])
823
u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />'
824
>>> w.render('name', 'john__lennon')
825
u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />'
826
>>> w.render('name', 'john__lennon', attrs={'id':'foo'})
827
u'<input id="foo_0" type="text" class="big" value="john" name="name_0" /><br /><input id="foo_1" type="text" class="small" value="lennon" name="name_1" />'
828
>>> w = MyMultiWidget(widgets=(TextInput(attrs={'class': 'big'}), TextInput(attrs={'class': 'small'})), attrs={'id': 'bar'})
829
>>> w.render('name', ['john', 'lennon'])
830
u'<input id="bar_0" type="text" class="big" value="john" name="name_0" /><br /><input id="bar_1" type="text" class="small" value="lennon" name="name_1" />'
832
# SplitDateTimeWidget #########################################################
834
>>> w = SplitDateTimeWidget()
835
>>> w.render('date', '')
836
u'<input type="text" name="date_0" /><input type="text" name="date_1" />'
837
>>> w.render('date', None)
838
u'<input type="text" name="date_0" /><input type="text" name="date_1" />'
839
>>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30))
840
u'<input type="text" name="date_0" value="2006-01-10" /><input type="text" name="date_1" value="07:30:00" />'
841
>>> w.render('date', [datetime.date(2006, 1, 10), datetime.time(7, 30)])
842
u'<input type="text" name="date_0" value="2006-01-10" /><input type="text" name="date_1" value="07:30:00" />'
844
You can also pass 'attrs' to the constructor. In this case, the attrs will be
845
included on both widgets.
846
>>> w = SplitDateTimeWidget(attrs={'class': 'pretty'})
847
>>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30))
848
u'<input type="text" class="pretty" value="2006-01-10" name="date_0" /><input type="text" class="pretty" value="07:30:00" name="date_1" />'
854
Each Field class does some sort of validation. Each Field has a clean() method,
855
which either raises django.newforms.ValidationError or returns the "clean"
856
data -- usually a Unicode object, but, in some rare cases, a list.
858
Each Field's __init__() takes at least these parameters:
859
required -- Boolean that specifies whether the field is required.
861
widget -- A Widget class, or instance of a Widget class, that should be
862
used for this Field when displaying it. Each Field has a default
863
Widget that it'll use if you don't specify this. In most cases,
864
the default widget is TextInput.
865
label -- A verbose name for this field, for use in displaying this field in
866
a form. By default, Django will use a "pretty" version of the form
867
field name, if the Field is part of a Form.
868
initial -- A value to use in this Field's initial display. This value is
869
*not* used as a fallback if data isn't given.
871
Other than that, the Field subclasses have class-specific options for
872
__init__(). For example, CharField has a max_length option.
874
# CharField ###################################################################
882
Traceback (most recent call last):
884
ValidationError: [u'This field is required.']
886
Traceback (most recent call last):
888
ValidationError: [u'This field is required.']
889
>>> f.clean([1, 2, 3])
892
>>> f = CharField(required=False)
901
>>> f.clean([1, 2, 3])
904
CharField accepts an optional max_length parameter:
905
>>> f = CharField(max_length=10, required=False)
908
>>> f.clean('1234567890')
910
>>> f.clean('1234567890a')
911
Traceback (most recent call last):
913
ValidationError: [u'Ensure this value has at most 10 characters (it has 11).']
915
CharField accepts an optional min_length parameter:
916
>>> f = CharField(min_length=10, required=False)
920
Traceback (most recent call last):
922
ValidationError: [u'Ensure this value has at least 10 characters (it has 5).']
923
>>> f.clean('1234567890')
925
>>> f.clean('1234567890a')
928
>>> f = CharField(min_length=10, required=True)
930
Traceback (most recent call last):
932
ValidationError: [u'This field is required.']
934
Traceback (most recent call last):
936
ValidationError: [u'Ensure this value has at least 10 characters (it has 5).']
937
>>> f.clean('1234567890')
939
>>> f.clean('1234567890a')
942
# IntegerField ################################################################
944
>>> f = IntegerField()
946
Traceback (most recent call last):
948
ValidationError: [u'This field is required.']
950
Traceback (most recent call last):
952
ValidationError: [u'This field is required.']
955
>>> isinstance(f.clean('1'), int)
960
Traceback (most recent call last):
962
ValidationError: [u'Enter a whole number.']
970
Traceback (most recent call last):
972
ValidationError: [u'Enter a whole number.']
974
>>> f = IntegerField(required=False)
976
>>> repr(f.clean(''))
979
>>> repr(f.clean(None))
983
>>> isinstance(f.clean('1'), int)
988
Traceback (most recent call last):
990
ValidationError: [u'Enter a whole number.']
998
Traceback (most recent call last):
1000
ValidationError: [u'Enter a whole number.']
1002
IntegerField accepts an optional max_value parameter:
1003
>>> f = IntegerField(max_value=10)
1005
Traceback (most recent call last):
1007
ValidationError: [u'This field is required.']
1013
Traceback (most recent call last):
1015
ValidationError: [u'Ensure this value is less than or equal to 10.']
1019
Traceback (most recent call last):
1021
ValidationError: [u'Ensure this value is less than or equal to 10.']
1023
IntegerField accepts an optional min_value parameter:
1024
>>> f = IntegerField(min_value=10)
1026
Traceback (most recent call last):
1028
ValidationError: [u'This field is required.']
1030
Traceback (most recent call last):
1032
ValidationError: [u'Ensure this value is greater than or equal to 10.']
1042
min_value and max_value can be used together:
1043
>>> f = IntegerField(min_value=10, max_value=20)
1045
Traceback (most recent call last):
1047
ValidationError: [u'This field is required.']
1049
Traceback (most recent call last):
1051
ValidationError: [u'Ensure this value is greater than or equal to 10.']
1063
Traceback (most recent call last):
1065
ValidationError: [u'Ensure this value is less than or equal to 20.']
1067
# FloatField ##################################################################
1069
>>> f = FloatField()
1071
Traceback (most recent call last):
1073
ValidationError: [u'This field is required.']
1075
Traceback (most recent call last):
1077
ValidationError: [u'This field is required.']
1080
>>> isinstance(f.clean('1'), float)
1087
Traceback (most recent call last):
1089
ValidationError: [u'Enter a number.']
1094
>>> f.clean(' 1.0 ')
1097
Traceback (most recent call last):
1099
ValidationError: [u'Enter a number.']
1101
>>> f = FloatField(required=False)
1109
FloatField accepts min_value and max_value just like IntegerField:
1110
>>> f = FloatField(max_value=1.5, min_value=0.5)
1113
Traceback (most recent call last):
1115
ValidationError: [u'Ensure this value is less than or equal to 1.5.']
1117
Traceback (most recent call last):
1119
ValidationError: [u'Ensure this value is greater than or equal to 0.5.']
1125
# DecimalField ################################################################
1127
>>> f = DecimalField(max_digits=4, decimal_places=2)
1129
Traceback (most recent call last):
1131
ValidationError: [u'This field is required.']
1133
Traceback (most recent call last):
1135
ValidationError: [u'This field is required.']
1138
>>> isinstance(f.clean('1'), Decimal)
1145
Traceback (most recent call last):
1147
ValidationError: [u'Enter a number.']
1152
>>> f.clean(' 1.0 ')
1155
Traceback (most recent call last):
1157
ValidationError: [u'Enter a number.']
1158
>>> f.clean('123.45')
1159
Traceback (most recent call last):
1161
ValidationError: [u'Ensure that there are no more than 4 digits in total.']
1162
>>> f.clean('1.234')
1163
Traceback (most recent call last):
1165
ValidationError: [u'Ensure that there are no more than 2 decimal places.']
1166
>>> f.clean('123.4')
1167
Traceback (most recent call last):
1169
ValidationError: [u'Ensure that there are no more than 2 digits before the decimal point.']
1170
>>> f = DecimalField(max_digits=4, decimal_places=2, required=False)
1178
DecimalField accepts min_value and max_value just like IntegerField:
1179
>>> f = DecimalField(max_digits=4, decimal_places=2, max_value=Decimal('1.5'), min_value=Decimal('0.5'))
1182
Traceback (most recent call last):
1184
ValidationError: [u'Ensure this value is less than or equal to 1.5.']
1186
Traceback (most recent call last):
1188
ValidationError: [u'Ensure this value is greater than or equal to 0.5.']
1195
>>> f.clean('00.50')
1198
# DateField ###################################################################
1202
>>> f.clean(datetime.date(2006, 10, 25))
1203
datetime.date(2006, 10, 25)
1204
>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30))
1205
datetime.date(2006, 10, 25)
1206
>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59))
1207
datetime.date(2006, 10, 25)
1208
>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200))
1209
datetime.date(2006, 10, 25)
1210
>>> f.clean('2006-10-25')
1211
datetime.date(2006, 10, 25)
1212
>>> f.clean('10/25/2006')
1213
datetime.date(2006, 10, 25)
1214
>>> f.clean('10/25/06')
1215
datetime.date(2006, 10, 25)
1216
>>> f.clean('Oct 25 2006')
1217
datetime.date(2006, 10, 25)
1218
>>> f.clean('October 25 2006')
1219
datetime.date(2006, 10, 25)
1220
>>> f.clean('October 25, 2006')
1221
datetime.date(2006, 10, 25)
1222
>>> f.clean('25 October 2006')
1223
datetime.date(2006, 10, 25)
1224
>>> f.clean('25 October, 2006')
1225
datetime.date(2006, 10, 25)
1226
>>> f.clean('2006-4-31')
1227
Traceback (most recent call last):
1229
ValidationError: [u'Enter a valid date.']
1230
>>> f.clean('200a-10-25')
1231
Traceback (most recent call last):
1233
ValidationError: [u'Enter a valid date.']
1234
>>> f.clean('25/10/06')
1235
Traceback (most recent call last):
1237
ValidationError: [u'Enter a valid date.']
1239
Traceback (most recent call last):
1241
ValidationError: [u'This field is required.']
1243
>>> f = DateField(required=False)
1245
>>> repr(f.clean(None))
1248
>>> repr(f.clean(''))
1251
DateField accepts an optional input_formats parameter:
1252
>>> f = DateField(input_formats=['%Y %m %d'])
1253
>>> f.clean(datetime.date(2006, 10, 25))
1254
datetime.date(2006, 10, 25)
1255
>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30))
1256
datetime.date(2006, 10, 25)
1257
>>> f.clean('2006 10 25')
1258
datetime.date(2006, 10, 25)
1260
The input_formats parameter overrides all default input formats,
1261
so the default formats won't work unless you specify them:
1262
>>> f.clean('2006-10-25')
1263
Traceback (most recent call last):
1265
ValidationError: [u'Enter a valid date.']
1266
>>> f.clean('10/25/2006')
1267
Traceback (most recent call last):
1269
ValidationError: [u'Enter a valid date.']
1270
>>> f.clean('10/25/06')
1271
Traceback (most recent call last):
1273
ValidationError: [u'Enter a valid date.']
1275
# TimeField ###################################################################
1279
>>> f.clean(datetime.time(14, 25))
1280
datetime.time(14, 25)
1281
>>> f.clean(datetime.time(14, 25, 59))
1282
datetime.time(14, 25, 59)
1283
>>> f.clean('14:25')
1284
datetime.time(14, 25)
1285
>>> f.clean('14:25:59')
1286
datetime.time(14, 25, 59)
1287
>>> f.clean('hello')
1288
Traceback (most recent call last):
1290
ValidationError: [u'Enter a valid time.']
1291
>>> f.clean('1:24 p.m.')
1292
Traceback (most recent call last):
1294
ValidationError: [u'Enter a valid time.']
1296
TimeField accepts an optional input_formats parameter:
1297
>>> f = TimeField(input_formats=['%I:%M %p'])
1298
>>> f.clean(datetime.time(14, 25))
1299
datetime.time(14, 25)
1300
>>> f.clean(datetime.time(14, 25, 59))
1301
datetime.time(14, 25, 59)
1302
>>> f.clean('4:25 AM')
1303
datetime.time(4, 25)
1304
>>> f.clean('4:25 PM')
1305
datetime.time(16, 25)
1307
The input_formats parameter overrides all default input formats,
1308
so the default formats won't work unless you specify them:
1309
>>> f.clean('14:30:45')
1310
Traceback (most recent call last):
1312
ValidationError: [u'Enter a valid time.']
1314
# DateTimeField ###############################################################
1317
>>> f = DateTimeField()
1318
>>> f.clean(datetime.date(2006, 10, 25))
1319
datetime.datetime(2006, 10, 25, 0, 0)
1320
>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30))
1321
datetime.datetime(2006, 10, 25, 14, 30)
1322
>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59))
1323
datetime.datetime(2006, 10, 25, 14, 30, 59)
1324
>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200))
1325
datetime.datetime(2006, 10, 25, 14, 30, 59, 200)
1326
>>> f.clean('2006-10-25 14:30:45')
1327
datetime.datetime(2006, 10, 25, 14, 30, 45)
1328
>>> f.clean('2006-10-25 14:30:00')
1329
datetime.datetime(2006, 10, 25, 14, 30)
1330
>>> f.clean('2006-10-25 14:30')
1331
datetime.datetime(2006, 10, 25, 14, 30)
1332
>>> f.clean('2006-10-25')
1333
datetime.datetime(2006, 10, 25, 0, 0)
1334
>>> f.clean('10/25/2006 14:30:45')
1335
datetime.datetime(2006, 10, 25, 14, 30, 45)
1336
>>> f.clean('10/25/2006 14:30:00')
1337
datetime.datetime(2006, 10, 25, 14, 30)
1338
>>> f.clean('10/25/2006 14:30')
1339
datetime.datetime(2006, 10, 25, 14, 30)
1340
>>> f.clean('10/25/2006')
1341
datetime.datetime(2006, 10, 25, 0, 0)
1342
>>> f.clean('10/25/06 14:30:45')
1343
datetime.datetime(2006, 10, 25, 14, 30, 45)
1344
>>> f.clean('10/25/06 14:30:00')
1345
datetime.datetime(2006, 10, 25, 14, 30)
1346
>>> f.clean('10/25/06 14:30')
1347
datetime.datetime(2006, 10, 25, 14, 30)
1348
>>> f.clean('10/25/06')
1349
datetime.datetime(2006, 10, 25, 0, 0)
1350
>>> f.clean('hello')
1351
Traceback (most recent call last):
1353
ValidationError: [u'Enter a valid date/time.']
1354
>>> f.clean('2006-10-25 4:30 p.m.')
1355
Traceback (most recent call last):
1357
ValidationError: [u'Enter a valid date/time.']
1359
DateField accepts an optional input_formats parameter:
1360
>>> f = DateTimeField(input_formats=['%Y %m %d %I:%M %p'])
1361
>>> f.clean(datetime.date(2006, 10, 25))
1362
datetime.datetime(2006, 10, 25, 0, 0)
1363
>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30))
1364
datetime.datetime(2006, 10, 25, 14, 30)
1365
>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59))
1366
datetime.datetime(2006, 10, 25, 14, 30, 59)
1367
>>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200))
1368
datetime.datetime(2006, 10, 25, 14, 30, 59, 200)
1369
>>> f.clean('2006 10 25 2:30 PM')
1370
datetime.datetime(2006, 10, 25, 14, 30)
1372
The input_formats parameter overrides all default input formats,
1373
so the default formats won't work unless you specify them:
1374
>>> f.clean('2006-10-25 14:30:45')
1375
Traceback (most recent call last):
1377
ValidationError: [u'Enter a valid date/time.']
1379
>>> f = DateTimeField(required=False)
1381
>>> repr(f.clean(None))
1384
>>> repr(f.clean(''))
1387
# RegexField ##################################################################
1389
>>> f = RegexField('^\d[A-F]\d$')
1395
Traceback (most recent call last):
1397
ValidationError: [u'Enter a valid value.']
1399
Traceback (most recent call last):
1401
ValidationError: [u'Enter a valid value.']
1403
Traceback (most recent call last):
1405
ValidationError: [u'Enter a valid value.']
1407
Traceback (most recent call last):
1409
ValidationError: [u'This field is required.']
1411
>>> f = RegexField('^\d[A-F]\d$', required=False)
1417
Traceback (most recent call last):
1419
ValidationError: [u'Enter a valid value.']
1423
Alternatively, RegexField can take a compiled regular expression:
1424
>>> f = RegexField(re.compile('^\d[A-F]\d$'))
1430
Traceback (most recent call last):
1432
ValidationError: [u'Enter a valid value.']
1434
Traceback (most recent call last):
1436
ValidationError: [u'Enter a valid value.']
1438
Traceback (most recent call last):
1440
ValidationError: [u'Enter a valid value.']
1442
RegexField takes an optional error_message argument:
1443
>>> f = RegexField('^\d\d\d\d$', error_message='Enter a four-digit number.')
1447
Traceback (most recent call last):
1449
ValidationError: [u'Enter a four-digit number.']
1451
Traceback (most recent call last):
1453
ValidationError: [u'Enter a four-digit number.']
1455
RegexField also access min_length and max_length parameters, for convenience.
1456
>>> f = RegexField('^\d+$', min_length=5, max_length=10)
1458
Traceback (most recent call last):
1460
ValidationError: [u'Ensure this value has at least 5 characters (it has 3).']
1462
Traceback (most recent call last):
1464
ValidationError: [u'Ensure this value has at least 5 characters (it has 3).']
1465
>>> f.clean('12345')
1467
>>> f.clean('1234567890')
1469
>>> f.clean('12345678901')
1470
Traceback (most recent call last):
1472
ValidationError: [u'Ensure this value has at most 10 characters (it has 11).']
1473
>>> f.clean('12345a')
1474
Traceback (most recent call last):
1476
ValidationError: [u'Enter a valid value.']
1478
# EmailField ##################################################################
1480
>>> f = EmailField()
1482
Traceback (most recent call last):
1484
ValidationError: [u'This field is required.']
1486
Traceback (most recent call last):
1488
ValidationError: [u'This field is required.']
1489
>>> f.clean('person@example.com')
1490
u'person@example.com'
1492
Traceback (most recent call last):
1494
ValidationError: [u'Enter a valid e-mail address.']
1496
Traceback (most recent call last):
1498
ValidationError: [u'Enter a valid e-mail address.']
1499
>>> f.clean('foo@bar')
1500
Traceback (most recent call last):
1502
ValidationError: [u'Enter a valid e-mail address.']
1504
>>> f = EmailField(required=False)
1509
>>> f.clean('person@example.com')
1510
u'person@example.com'
1512
Traceback (most recent call last):
1514
ValidationError: [u'Enter a valid e-mail address.']
1516
Traceback (most recent call last):
1518
ValidationError: [u'Enter a valid e-mail address.']
1519
>>> f.clean('foo@bar')
1520
Traceback (most recent call last):
1522
ValidationError: [u'Enter a valid e-mail address.']
1524
EmailField also access min_length and max_length parameters, for convenience.
1525
>>> f = EmailField(min_length=10, max_length=15)
1526
>>> f.clean('a@foo.com')
1527
Traceback (most recent call last):
1529
ValidationError: [u'Ensure this value has at least 10 characters (it has 9).']
1530
>>> f.clean('alf@foo.com')
1532
>>> f.clean('alf123456788@foo.com')
1533
Traceback (most recent call last):
1535
ValidationError: [u'Ensure this value has at most 15 characters (it has 20).']
1537
# FileField ##################################################################
1541
Traceback (most recent call last):
1543
ValidationError: [u'This field is required.']
1546
Traceback (most recent call last):
1548
ValidationError: [u'This field is required.']
1551
Traceback (most recent call last):
1553
ValidationError: [u'No file was submitted.']
1555
>>> f.clean('some content that is not a file')
1556
Traceback (most recent call last):
1558
ValidationError: [u'No file was submitted. Check the encoding type on the form.']
1560
>>> f.clean({'filename': 'name', 'content':None})
1561
Traceback (most recent call last):
1563
ValidationError: [u'The submitted file is empty.']
1565
>>> f.clean({'filename': 'name', 'content':''})
1566
Traceback (most recent call last):
1568
ValidationError: [u'The submitted file is empty.']
1570
>>> type(f.clean({'filename': 'name', 'content':'Some File Content'}))
1571
<class 'django.newforms.fields.UploadedFile'>
1573
# URLField ##################################################################
1577
Traceback (most recent call last):
1579
ValidationError: [u'This field is required.']
1581
Traceback (most recent call last):
1583
ValidationError: [u'This field is required.']
1584
>>> f.clean('http://example.com')
1585
u'http://example.com'
1586
>>> f.clean('http://www.example.com')
1587
u'http://www.example.com'
1589
Traceback (most recent call last):
1591
ValidationError: [u'Enter a valid URL.']
1592
>>> f.clean('example.com')
1593
Traceback (most recent call last):
1595
ValidationError: [u'Enter a valid URL.']
1596
>>> f.clean('http://')
1597
Traceback (most recent call last):
1599
ValidationError: [u'Enter a valid URL.']
1600
>>> f.clean('http://example')
1601
Traceback (most recent call last):
1603
ValidationError: [u'Enter a valid URL.']
1604
>>> f.clean('http://example.')
1605
Traceback (most recent call last):
1607
ValidationError: [u'Enter a valid URL.']
1608
>>> f.clean('http://.com')
1609
Traceback (most recent call last):
1611
ValidationError: [u'Enter a valid URL.']
1613
>>> f = URLField(required=False)
1618
>>> f.clean('http://example.com')
1619
u'http://example.com'
1620
>>> f.clean('http://www.example.com')
1621
u'http://www.example.com'
1623
Traceback (most recent call last):
1625
ValidationError: [u'Enter a valid URL.']
1626
>>> f.clean('example.com')
1627
Traceback (most recent call last):
1629
ValidationError: [u'Enter a valid URL.']
1630
>>> f.clean('http://')
1631
Traceback (most recent call last):
1633
ValidationError: [u'Enter a valid URL.']
1634
>>> f.clean('http://example')
1635
Traceback (most recent call last):
1637
ValidationError: [u'Enter a valid URL.']
1638
>>> f.clean('http://example.')
1639
Traceback (most recent call last):
1641
ValidationError: [u'Enter a valid URL.']
1642
>>> f.clean('http://.com')
1643
Traceback (most recent call last):
1645
ValidationError: [u'Enter a valid URL.']
1647
URLField takes an optional verify_exists parameter, which is False by default.
1648
This verifies that the URL is live on the Internet and doesn't return a 404 or 500:
1649
>>> f = URLField(verify_exists=True)
1650
>>> f.clean('http://www.google.com') # This will fail if there's no Internet connection
1651
u'http://www.google.com'
1652
>>> f.clean('http://example')
1653
Traceback (most recent call last):
1655
ValidationError: [u'Enter a valid URL.']
1656
>>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com') # bad domain
1657
Traceback (most recent call last):
1659
ValidationError: [u'This URL appears to be a broken link.']
1660
>>> f.clean('http://google.com/we-love-microsoft.html') # good domain, bad page
1661
Traceback (most recent call last):
1663
ValidationError: [u'This URL appears to be a broken link.']
1664
>>> f = URLField(verify_exists=True, required=False)
1667
>>> f.clean('http://www.google.com') # This will fail if there's no Internet connection
1668
u'http://www.google.com'
1670
URLField also access min_length and max_length parameters, for convenience.
1671
>>> f = URLField(min_length=15, max_length=20)
1672
>>> f.clean('http://f.com')
1673
Traceback (most recent call last):
1675
ValidationError: [u'Ensure this value has at least 15 characters (it has 12).']
1676
>>> f.clean('http://example.com')
1677
u'http://example.com'
1678
>>> f.clean('http://abcdefghijklmnopqrstuvwxyz.com')
1679
Traceback (most recent call last):
1681
ValidationError: [u'Ensure this value has at most 20 characters (it has 37).']
1683
# BooleanField ################################################################
1685
>>> f = BooleanField()
1687
Traceback (most recent call last):
1689
ValidationError: [u'This field is required.']
1691
Traceback (most recent call last):
1693
ValidationError: [u'This field is required.']
1702
>>> f.clean('Django rocks')
1705
>>> f = BooleanField(required=False)
1718
>>> f.clean('Django rocks')
1721
# ChoiceField #################################################################
1723
>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')])
1725
Traceback (most recent call last):
1727
ValidationError: [u'This field is required.']
1729
Traceback (most recent call last):
1731
ValidationError: [u'This field is required.']
1737
Traceback (most recent call last):
1739
ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
1741
>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')], required=False)
1751
Traceback (most recent call last):
1753
ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
1755
>>> f = ChoiceField(choices=[('J', 'John'), ('P', 'Paul')])
1759
Traceback (most recent call last):
1761
ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
1763
# NullBooleanField ############################################################
1765
>>> f = NullBooleanField()
1775
>>> f.clean('hello')
1777
# MultipleChoiceField #########################################################
1779
>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')])
1781
Traceback (most recent call last):
1783
ValidationError: [u'This field is required.']
1785
Traceback (most recent call last):
1787
ValidationError: [u'This field is required.']
1792
>>> f.clean(['1', '2'])
1794
>>> f.clean([1, '2'])
1796
>>> f.clean((1, '2'))
1798
>>> f.clean('hello')
1799
Traceback (most recent call last):
1801
ValidationError: [u'Enter a list of values.']
1803
Traceback (most recent call last):
1805
ValidationError: [u'This field is required.']
1807
Traceback (most recent call last):
1809
ValidationError: [u'This field is required.']
1811
Traceback (most recent call last):
1813
ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
1815
>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')], required=False)
1824
>>> f.clean(['1', '2'])
1826
>>> f.clean([1, '2'])
1828
>>> f.clean((1, '2'))
1830
>>> f.clean('hello')
1831
Traceback (most recent call last):
1833
ValidationError: [u'Enter a list of values.']
1839
Traceback (most recent call last):
1841
ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
1843
# ComboField ##################################################################
1845
ComboField takes a list of fields that should be used to validate a value,
1847
>>> f = ComboField(fields=[CharField(max_length=20), EmailField()])
1848
>>> f.clean('test@example.com')
1850
>>> f.clean('longemailaddress@example.com')
1851
Traceback (most recent call last):
1853
ValidationError: [u'Ensure this value has at most 20 characters (it has 28).']
1854
>>> f.clean('not an e-mail')
1855
Traceback (most recent call last):
1857
ValidationError: [u'Enter a valid e-mail address.']
1859
Traceback (most recent call last):
1861
ValidationError: [u'This field is required.']
1863
Traceback (most recent call last):
1865
ValidationError: [u'This field is required.']
1867
>>> f = ComboField(fields=[CharField(max_length=20), EmailField()], required=False)
1868
>>> f.clean('test@example.com')
1870
>>> f.clean('longemailaddress@example.com')
1871
Traceback (most recent call last):
1873
ValidationError: [u'Ensure this value has at most 20 characters (it has 28).']
1874
>>> f.clean('not an e-mail')
1875
Traceback (most recent call last):
1877
ValidationError: [u'Enter a valid e-mail address.']
1883
# SplitDateTimeField ##########################################################
1885
>>> f = SplitDateTimeField()
1886
>>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)])
1887
datetime.datetime(2006, 1, 10, 7, 30)
1889
Traceback (most recent call last):
1891
ValidationError: [u'This field is required.']
1893
Traceback (most recent call last):
1895
ValidationError: [u'This field is required.']
1896
>>> f.clean('hello')
1897
Traceback (most recent call last):
1899
ValidationError: [u'Enter a list of values.']
1900
>>> f.clean(['hello', 'there'])
1901
Traceback (most recent call last):
1903
ValidationError: [u'Enter a valid date.', u'Enter a valid time.']
1904
>>> f.clean(['2006-01-10', 'there'])
1905
Traceback (most recent call last):
1907
ValidationError: [u'Enter a valid time.']
1908
>>> f.clean(['hello', '07:30'])
1909
Traceback (most recent call last):
1911
ValidationError: [u'Enter a valid date.']
1913
>>> f = SplitDateTimeField(required=False)
1914
>>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)])
1915
datetime.datetime(2006, 1, 10, 7, 30)
1916
>>> f.clean(['2006-01-10', '07:30'])
1917
datetime.datetime(2006, 1, 10, 7, 30)
1921
>>> f.clean(['', ''])
1922
>>> f.clean('hello')
1923
Traceback (most recent call last):
1925
ValidationError: [u'Enter a list of values.']
1926
>>> f.clean(['hello', 'there'])
1927
Traceback (most recent call last):
1929
ValidationError: [u'Enter a valid date.', u'Enter a valid time.']
1930
>>> f.clean(['2006-01-10', 'there'])
1931
Traceback (most recent call last):
1933
ValidationError: [u'Enter a valid time.']
1934
>>> f.clean(['hello', '07:30'])
1935
Traceback (most recent call last):
1937
ValidationError: [u'Enter a valid date.']
1938
>>> f.clean(['2006-01-10', ''])
1939
Traceback (most recent call last):
1941
ValidationError: [u'Enter a valid time.']
1942
>>> f.clean(['2006-01-10'])
1943
Traceback (most recent call last):
1945
ValidationError: [u'Enter a valid time.']
1946
>>> f.clean(['', '07:30'])
1947
Traceback (most recent call last):
1949
ValidationError: [u'Enter a valid date.']
1955
A Form is a collection of Fields. It knows how to validate a set of data and it
1956
knows how to render itself in a couple of default ways (e.g., an HTML table).
1957
You can pass it data in __init__(), as a dictionary.
1959
# Form ########################################################################
1961
>>> class Person(Form):
1962
... first_name = CharField()
1963
... last_name = CharField()
1964
... birthday = DateField()
1966
Pass a dictionary to a Form's __init__().
1967
>>> p = Person({'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9'})
1974
>>> p.errors.as_ul()
1976
>>> p.errors.as_text()
1979
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
1980
>>> print p['first_name']
1981
<input type="text" name="first_name" value="John" id="id_first_name" />
1982
>>> print p['last_name']
1983
<input type="text" name="last_name" value="Lennon" id="id_last_name" />
1984
>>> print p['birthday']
1985
<input type="text" name="birthday" value="1940-10-9" id="id_birthday" />
1986
>>> print p['nonexistentfield']
1987
Traceback (most recent call last):
1989
KeyError: "Key 'nonexistentfield' not found in Form"
1991
>>> for boundfield in p:
1992
... print boundfield
1993
<input type="text" name="first_name" value="John" id="id_first_name" />
1994
<input type="text" name="last_name" value="Lennon" id="id_last_name" />
1995
<input type="text" name="birthday" value="1940-10-9" id="id_birthday" />
1996
>>> for boundfield in p:
1997
... print boundfield.label, boundfield.data
2002
<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>
2003
<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="Lennon" id="id_last_name" /></td></tr>
2004
<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr>
2006
Empty dictionaries are valid, too.
2011
{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']}
2015
Traceback (most recent call last):
2017
AttributeError: 'Person' object has no attribute 'cleaned_data'
2019
<tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr>
2020
<tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr>
2021
<tr><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr>
2022
>>> print p.as_table()
2023
<tr><th><label for="id_first_name">First name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="first_name" id="id_first_name" /></td></tr>
2024
<tr><th><label for="id_last_name">Last name:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="last_name" id="id_last_name" /></td></tr>
2025
<tr><th><label for="id_birthday">Birthday:</label></th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="birthday" id="id_birthday" /></td></tr>
2027
<li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
2028
<li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
2029
<li><ul class="errorlist"><li>This field is required.</li></ul><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li>
2031
<ul class="errorlist"><li>This field is required.</li></ul>
2032
<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
2033
<ul class="errorlist"><li>This field is required.</li></ul>
2034
<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
2035
<ul class="errorlist"><li>This field is required.</li></ul>
2036
<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p>
2038
If you don't pass any values to the Form's __init__(), or if you pass None,
2039
the Form will be considered unbound and won't do any validation. Form.errors
2040
will be an empty dictionary *but* Form.is_valid() will return False.
2049
Traceback (most recent call last):
2051
AttributeError: 'Person' object has no attribute 'cleaned_data'
2053
<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr>
2054
<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
2055
<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr>
2056
>>> print p.as_table()
2057
<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr>
2058
<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
2059
<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr>
2061
<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
2062
<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
2063
<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li>
2065
<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
2066
<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
2067
<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p>
2069
Unicode values are handled properly.
2070
>>> p = Person({'first_name': u'John', 'last_name': u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111', 'birthday': '1940-10-9'})
2072
u'<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" value="John" id="id_first_name" /></td></tr>\n<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></td></tr>\n<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr>'
2074
u'<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" value="John" id="id_first_name" /></li>\n<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></li>\n<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></li>'
2076
u'<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" value="John" id="id_first_name" /></p>\n<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" id="id_last_name" /></p>\n<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></p>'
2078
>>> p = Person({'last_name': u'Lennon'})
2080
{'first_name': [u'This field is required.'], 'birthday': [u'This field is required.']}
2083
>>> p.errors.as_ul()
2084
u'<ul class="errorlist"><li>first_name<ul class="errorlist"><li>This field is required.</li></ul></li><li>birthday<ul class="errorlist"><li>This field is required.</li></ul></li></ul>'
2085
>>> print p.errors.as_text()
2087
* This field is required.
2089
* This field is required.
2091
Traceback (most recent call last):
2093
AttributeError: 'Person' object has no attribute 'cleaned_data'
2094
>>> p['first_name'].errors
2095
[u'This field is required.']
2096
>>> p['first_name'].errors.as_ul()
2097
u'<ul class="errorlist"><li>This field is required.</li></ul>'
2098
>>> p['first_name'].errors.as_text()
2099
u'* This field is required.'
2102
>>> print p['first_name']
2103
<input type="text" name="first_name" id="id_first_name" />
2104
>>> print p['last_name']
2105
<input type="text" name="last_name" id="id_last_name" />
2106
>>> print p['birthday']
2107
<input type="text" name="birthday" id="id_birthday" />
2109
cleaned_data will always *only* contain a key for fields defined in the
2110
Form, even if you pass extra data when you define the Form. In this
2111
example, we pass a bunch of extra fields to the form constructor,
2112
but cleaned_data contains only the form's fields.
2113
>>> data = {'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9', 'extra1': 'hello', 'extra2': 'hello'}
2114
>>> p = Person(data)
2118
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
2120
cleaned_data will include a key and value for *all* fields defined in the Form,
2121
even if the Form's data didn't include a value for fields that are not
2122
required. In this example, the data dictionary doesn't include a value for the
2123
"nick_name" field, but cleaned_data includes it. For CharFields, it's set to the
2125
>>> class OptionalPersonForm(Form):
2126
... first_name = CharField()
2127
... last_name = CharField()
2128
... nick_name = CharField(required=False)
2129
>>> data = {'first_name': u'John', 'last_name': u'Lennon'}
2130
>>> f = OptionalPersonForm(data)
2134
{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
2136
For DateFields, it's set to None.
2137
>>> class OptionalPersonForm(Form):
2138
... first_name = CharField()
2139
... last_name = CharField()
2140
... birth_date = DateField(required=False)
2141
>>> data = {'first_name': u'John', 'last_name': u'Lennon'}
2142
>>> f = OptionalPersonForm(data)
2146
{'birth_date': None, 'first_name': u'John', 'last_name': u'Lennon'}
2148
"auto_id" tells the Form to add an "id" attribute to each form element.
2149
If it's a string that contains '%s', Django will use that as a format string
2150
into which the field's name will be inserted. It will also put a <label> around
2151
the human-readable labels for a field.
2152
>>> p = Person(auto_id='%s_id')
2153
>>> print p.as_table()
2154
<tr><th><label for="first_name_id">First name:</label></th><td><input type="text" name="first_name" id="first_name_id" /></td></tr>
2155
<tr><th><label for="last_name_id">Last name:</label></th><td><input type="text" name="last_name" id="last_name_id" /></td></tr>
2156
<tr><th><label for="birthday_id">Birthday:</label></th><td><input type="text" name="birthday" id="birthday_id" /></td></tr>
2158
<li><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></li>
2159
<li><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></li>
2160
<li><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></li>
2162
<p><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></p>
2163
<p><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></p>
2164
<p><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></p>
2166
If auto_id is any True value whose str() does not contain '%s', the "id"
2167
attribute will be the name of the field.
2168
>>> p = Person(auto_id=True)
2170
<li><label for="first_name">First name:</label> <input type="text" name="first_name" id="first_name" /></li>
2171
<li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li>
2172
<li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li>
2174
If auto_id is any False value, an "id" attribute won't be output unless it
2175
was manually entered.
2176
>>> p = Person(auto_id=False)
2178
<li>First name: <input type="text" name="first_name" /></li>
2179
<li>Last name: <input type="text" name="last_name" /></li>
2180
<li>Birthday: <input type="text" name="birthday" /></li>
2182
In this example, auto_id is False, but the "id" attribute for the "first_name"
2183
field is given. Also note that field gets a <label>, while the others don't.
2184
>>> class PersonNew(Form):
2185
... first_name = CharField(widget=TextInput(attrs={'id': 'first_name_id'}))
2186
... last_name = CharField()
2187
... birthday = DateField()
2188
>>> p = PersonNew(auto_id=False)
2190
<li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li>
2191
<li>Last name: <input type="text" name="last_name" /></li>
2192
<li>Birthday: <input type="text" name="birthday" /></li>
2194
If the "id" attribute is specified in the Form and auto_id is True, the "id"
2195
attribute in the Form gets precedence.
2196
>>> p = PersonNew(auto_id=True)
2198
<li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li>
2199
<li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li>
2200
<li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li>
2202
>>> class SignupForm(Form):
2203
... email = EmailField()
2204
... get_spam = BooleanField()
2205
>>> f = SignupForm(auto_id=False)
2206
>>> print f['email']
2207
<input type="text" name="email" />
2208
>>> print f['get_spam']
2209
<input type="checkbox" name="get_spam" />
2211
>>> f = SignupForm({'email': 'test@example.com', 'get_spam': True}, auto_id=False)
2212
>>> print f['email']
2213
<input type="text" name="email" value="test@example.com" />
2214
>>> print f['get_spam']
2215
<input checked="checked" type="checkbox" name="get_spam" />
2217
Any Field can have a Widget class passed to its constructor:
2218
>>> class ContactForm(Form):
2219
... subject = CharField()
2220
... message = CharField(widget=Textarea)
2221
>>> f = ContactForm(auto_id=False)
2222
>>> print f['subject']
2223
<input type="text" name="subject" />
2224
>>> print f['message']
2225
<textarea rows="10" cols="40" name="message"></textarea>
2227
as_textarea(), as_text() and as_hidden() are shortcuts for changing the output
2229
>>> f['subject'].as_textarea()
2230
u'<textarea rows="10" cols="40" name="subject"></textarea>'
2231
>>> f['message'].as_text()
2232
u'<input type="text" name="message" />'
2233
>>> f['message'].as_hidden()
2234
u'<input type="hidden" name="message" />'
2236
The 'widget' parameter to a Field can also be an instance:
2237
>>> class ContactForm(Form):
2238
... subject = CharField()
2239
... message = CharField(widget=Textarea(attrs={'rows': 80, 'cols': 20}))
2240
>>> f = ContactForm(auto_id=False)
2241
>>> print f['message']
2242
<textarea rows="80" cols="20" name="message"></textarea>
2244
Instance-level attrs are *not* carried over to as_textarea(), as_text() and
2246
>>> f['message'].as_text()
2247
u'<input type="text" name="message" />'
2248
>>> f = ContactForm({'subject': 'Hello', 'message': 'I love you.'}, auto_id=False)
2249
>>> f['subject'].as_textarea()
2250
u'<textarea rows="10" cols="40" name="subject">Hello</textarea>'
2251
>>> f['message'].as_text()
2252
u'<input type="text" name="message" value="I love you." />'
2253
>>> f['message'].as_hidden()
2254
u'<input type="hidden" name="message" value="I love you." />'
2256
For a form with a <select>, use ChoiceField:
2257
>>> class FrameworkForm(Form):
2258
... name = CharField()
2259
... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')])
2260
>>> f = FrameworkForm(auto_id=False)
2261
>>> print f['language']
2262
<select name="language">
2263
<option value="P">Python</option>
2264
<option value="J">Java</option>
2266
>>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False)
2267
>>> print f['language']
2268
<select name="language">
2269
<option value="P" selected="selected">Python</option>
2270
<option value="J">Java</option>
2273
A subtlety: If one of the choices' value is the empty string and the form is
2274
unbound, then the <option> for the empty-string choice will get selected="selected".
2275
>>> class FrameworkForm(Form):
2276
... name = CharField()
2277
... language = ChoiceField(choices=[('', '------'), ('P', 'Python'), ('J', 'Java')])
2278
>>> f = FrameworkForm(auto_id=False)
2279
>>> print f['language']
2280
<select name="language">
2281
<option value="" selected="selected">------</option>
2282
<option value="P">Python</option>
2283
<option value="J">Java</option>
2286
You can specify widget attributes in the Widget constructor.
2287
>>> class FrameworkForm(Form):
2288
... name = CharField()
2289
... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=Select(attrs={'class': 'foo'}))
2290
>>> f = FrameworkForm(auto_id=False)
2291
>>> print f['language']
2292
<select class="foo" name="language">
2293
<option value="P">Python</option>
2294
<option value="J">Java</option>
2296
>>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False)
2297
>>> print f['language']
2298
<select class="foo" name="language">
2299
<option value="P" selected="selected">Python</option>
2300
<option value="J">Java</option>
2303
When passing a custom widget instance to ChoiceField, note that setting
2304
'choices' on the widget is meaningless. The widget will use the choices
2305
defined on the Field, not the ones defined on the Widget.
2306
>>> class FrameworkForm(Form):
2307
... name = CharField()
2308
... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=Select(choices=[('R', 'Ruby'), ('P', 'Perl')], attrs={'class': 'foo'}))
2309
>>> f = FrameworkForm(auto_id=False)
2310
>>> print f['language']
2311
<select class="foo" name="language">
2312
<option value="P">Python</option>
2313
<option value="J">Java</option>
2315
>>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False)
2316
>>> print f['language']
2317
<select class="foo" name="language">
2318
<option value="P" selected="selected">Python</option>
2319
<option value="J">Java</option>
2322
You can set a ChoiceField's choices after the fact.
2323
>>> class FrameworkForm(Form):
2324
... name = CharField()
2325
... language = ChoiceField()
2326
>>> f = FrameworkForm(auto_id=False)
2327
>>> print f['language']
2328
<select name="language">
2330
>>> f.fields['language'].choices = [('P', 'Python'), ('J', 'Java')]
2331
>>> print f['language']
2332
<select name="language">
2333
<option value="P">Python</option>
2334
<option value="J">Java</option>
2337
Add widget=RadioSelect to use that widget with a ChoiceField.
2338
>>> class FrameworkForm(Form):
2339
... name = CharField()
2340
... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=RadioSelect)
2341
>>> f = FrameworkForm(auto_id=False)
2342
>>> print f['language']
2344
<li><label><input type="radio" name="language" value="P" /> Python</label></li>
2345
<li><label><input type="radio" name="language" value="J" /> Java</label></li>
2348
<tr><th>Name:</th><td><input type="text" name="name" /></td></tr>
2349
<tr><th>Language:</th><td><ul>
2350
<li><label><input type="radio" name="language" value="P" /> Python</label></li>
2351
<li><label><input type="radio" name="language" value="J" /> Java</label></li>
2354
<li>Name: <input type="text" name="name" /></li>
2356
<li><label><input type="radio" name="language" value="P" /> Python</label></li>
2357
<li><label><input type="radio" name="language" value="J" /> Java</label></li>
2360
Regarding auto_id and <label>, RadioSelect is a special case. Each radio button
2361
gets a distinct ID, formed by appending an underscore plus the button's
2363
>>> f = FrameworkForm(auto_id='id_%s')
2364
>>> print f['language']
2366
<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
2367
<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
2370
When RadioSelect is used with auto_id, and the whole form is printed using
2371
either as_table() or as_ul(), the label for the RadioSelect will point to the
2372
ID of the *first* radio button.
2374
<tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" /></td></tr>
2375
<tr><th><label for="id_language_0">Language:</label></th><td><ul>
2376
<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
2377
<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
2380
<li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></li>
2381
<li><label for="id_language_0">Language:</label> <ul>
2382
<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
2383
<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
2386
<p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></p>
2387
<p><label for="id_language_0">Language:</label> <ul>
2388
<li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li>
2389
<li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li>
2392
MultipleChoiceField is a special case, as its data is required to be a list:
2393
>>> class SongForm(Form):
2394
... name = CharField()
2395
... composers = MultipleChoiceField()
2396
>>> f = SongForm(auto_id=False)
2397
>>> print f['composers']
2398
<select multiple="multiple" name="composers">
2400
>>> class SongForm(Form):
2401
... name = CharField()
2402
... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')])
2403
>>> f = SongForm(auto_id=False)
2404
>>> print f['composers']
2405
<select multiple="multiple" name="composers">
2406
<option value="J">John Lennon</option>
2407
<option value="P">Paul McCartney</option>
2409
>>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False)
2411
<input type="text" name="name" value="Yesterday" />
2412
>>> print f['composers']
2413
<select multiple="multiple" name="composers">
2414
<option value="J">John Lennon</option>
2415
<option value="P" selected="selected">Paul McCartney</option>
2418
MultipleChoiceField rendered as_hidden() is a special case. Because it can
2419
have multiple values, its as_hidden() renders multiple <input type="hidden">
2421
>>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False)
2422
>>> print f['composers'].as_hidden()
2423
<input type="hidden" name="composers" value="P" />
2424
>>> f = SongForm({'name': 'From Me To You', 'composers': ['P', 'J']}, auto_id=False)
2425
>>> print f['composers'].as_hidden()
2426
<input type="hidden" name="composers" value="P" />
2427
<input type="hidden" name="composers" value="J" />
2429
MultipleChoiceField can also be used with the CheckboxSelectMultiple widget.
2430
>>> class SongForm(Form):
2431
... name = CharField()
2432
... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=CheckboxSelectMultiple)
2433
>>> f = SongForm(auto_id=False)
2434
>>> print f['composers']
2436
<li><label><input type="checkbox" name="composers" value="J" /> John Lennon</label></li>
2437
<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
2439
>>> f = SongForm({'composers': ['J']}, auto_id=False)
2440
>>> print f['composers']
2442
<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li>
2443
<li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
2445
>>> f = SongForm({'composers': ['J', 'P']}, auto_id=False)
2446
>>> print f['composers']
2448
<li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li>
2449
<li><label><input checked="checked" type="checkbox" name="composers" value="P" /> Paul McCartney</label></li>
2452
Regarding auto_id, CheckboxSelectMultiple is a special case. Each checkbox
2453
gets a distinct ID, formed by appending an underscore plus the checkbox's
2455
>>> f = SongForm(auto_id='%s_id')
2456
>>> print f['composers']
2458
<li><label><input type="checkbox" name="composers" value="J" id="composers_id_0" /> John Lennon</label></li>
2459
<li><label><input type="checkbox" name="composers" value="P" id="composers_id_1" /> Paul McCartney</label></li>
2462
Data for a MultipleChoiceField should be a list. QueryDict and MultiValueDict
2463
conveniently work with this.
2464
>>> data = {'name': 'Yesterday', 'composers': ['J', 'P']}
2465
>>> f = SongForm(data)
2468
>>> from django.http import QueryDict
2469
>>> data = QueryDict('name=Yesterday&composers=J&composers=P')
2470
>>> f = SongForm(data)
2473
>>> from django.utils.datastructures import MultiValueDict
2474
>>> data = MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P']))
2475
>>> f = SongForm(data)
2479
The MultipleHiddenInput widget renders multiple values as hidden fields.
2480
>>> class SongFormHidden(Form):
2481
... name = CharField()
2482
... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=MultipleHiddenInput)
2483
>>> f = SongFormHidden(MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])), auto_id=False)
2485
<li>Name: <input type="text" name="name" value="Yesterday" /><input type="hidden" name="composers" value="J" />
2486
<input type="hidden" name="composers" value="P" /></li>
2488
When using CheckboxSelectMultiple, the framework expects a list of input and
2489
returns a list of input.
2490
>>> f = SongForm({'name': 'Yesterday'}, auto_id=False)
2492
{'composers': [u'This field is required.']}
2493
>>> f = SongForm({'name': 'Yesterday', 'composers': ['J']}, auto_id=False)
2497
{'composers': [u'J'], 'name': u'Yesterday'}
2498
>>> f = SongForm({'name': 'Yesterday', 'composers': ['J', 'P']}, auto_id=False)
2502
{'composers': [u'J', u'P'], 'name': u'Yesterday'}
2504
Validation errors are HTML-escaped when output as HTML.
2505
>>> class EscapingForm(Form):
2506
... special_name = CharField()
2507
... def clean_special_name(self):
2508
... raise ValidationError("Something's wrong with '%s'" % self.cleaned_data['special_name'])
2510
>>> f = EscapingForm({'special_name': "Nothing to escape"}, auto_id=False)
2512
<tr><th>Special name:</th><td><ul class="errorlist"><li>Something's wrong with 'Nothing to escape'</li></ul><input type="text" name="special_name" value="Nothing to escape" /></td></tr>
2513
>>> f = EscapingForm({'special_name': "Should escape < & > and <script>alert('xss')</script>"}, auto_id=False)
2515
<tr><th>Special name:</th><td><ul class="errorlist"><li>Something's wrong with 'Should escape < & > and <script>alert('xss')</script>'</li></ul><input type="text" name="special_name" value="Should escape < & > and <script>alert('xss')</script>" /></td></tr>
2517
# Validating multiple fields in relation to another ###########################
2519
There are a couple of ways to do multiple-field validation. If you want the
2520
validation message to be associated with a particular field, implement the
2521
clean_XXX() method on the Form, where XXX is the field name. As in
2522
Field.clean(), the clean_XXX() method should return the cleaned value. In the
2523
clean_XXX() method, you have access to self.cleaned_data, which is a dictionary
2524
of all the data that has been cleaned *so far*, in order by the fields,
2525
including the current field (e.g., the field XXX if you're in clean_XXX()).
2526
>>> class UserRegistration(Form):
2527
... username = CharField(max_length=10)
2528
... password1 = CharField(widget=PasswordInput)
2529
... password2 = CharField(widget=PasswordInput)
2530
... def clean_password2(self):
2531
... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']:
2532
... raise ValidationError(u'Please make sure your passwords match.')
2533
... return self.cleaned_data['password2']
2534
>>> f = UserRegistration(auto_id=False)
2537
>>> f = UserRegistration({}, auto_id=False)
2539
{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']}
2540
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)
2542
{'password2': [u'Please make sure your passwords match.']}
2543
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False)
2547
{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'}
2549
Another way of doing multiple-field validation is by implementing the
2550
Form's clean() method. If you do this, any ValidationError raised by that
2551
method will not be associated with a particular field; it will have a
2552
special-case association with the field named '__all__'.
2553
Note that in Form.clean(), you have access to self.cleaned_data, a dictionary of
2554
all the fields/values that have *not* raised a ValidationError. Also note
2555
Form.clean() is required to return a dictionary of all clean data.
2556
>>> class UserRegistration(Form):
2557
... username = CharField(max_length=10)
2558
... password1 = CharField(widget=PasswordInput)
2559
... password2 = CharField(widget=PasswordInput)
2560
... def clean(self):
2561
... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']:
2562
... raise ValidationError(u'Please make sure your passwords match.')
2563
... return self.cleaned_data
2564
>>> f = UserRegistration(auto_id=False)
2567
>>> f = UserRegistration({}, auto_id=False)
2568
>>> print f.as_table()
2569
<tr><th>Username:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="username" maxlength="10" /></td></tr>
2570
<tr><th>Password1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password1" /></td></tr>
2571
<tr><th>Password2:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password2" /></td></tr>
2573
{'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']}
2574
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)
2576
{'__all__': [u'Please make sure your passwords match.']}
2577
>>> print f.as_table()
2578
<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr>
2579
<tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr>
2580
<tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr>
2581
<tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr>
2583
<li><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></li>
2584
<li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li>
2585
<li>Password1: <input type="password" name="password1" value="foo" /></li>
2586
<li>Password2: <input type="password" name="password2" value="bar" /></li>
2587
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False)
2591
{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'}
2593
# Dynamic construction ########################################################
2595
It's possible to construct a Form dynamically by adding to the self.fields
2596
dictionary in __init__(). Don't forget to call Form.__init__() within the
2597
subclass' __init__().
2598
>>> class Person(Form):
2599
... first_name = CharField()
2600
... last_name = CharField()
2601
... def __init__(self, *args, **kwargs):
2602
... super(Person, self).__init__(*args, **kwargs)
2603
... self.fields['birthday'] = DateField()
2604
>>> p = Person(auto_id=False)
2606
<tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr>
2607
<tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr>
2608
<tr><th>Birthday:</th><td><input type="text" name="birthday" /></td></tr>
2610
Instances of a dynamic Form do not persist fields from one Form instance to
2612
>>> class MyForm(Form):
2613
... def __init__(self, data=None, auto_id=False, field_list=[]):
2614
... Form.__init__(self, data, auto_id=auto_id)
2615
... for field in field_list:
2616
... self.fields[field[0]] = field[1]
2617
>>> field_list = [('field1', CharField()), ('field2', CharField())]
2618
>>> my_form = MyForm(field_list=field_list)
2620
<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
2621
<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr>
2622
>>> field_list = [('field3', CharField()), ('field4', CharField())]
2623
>>> my_form = MyForm(field_list=field_list)
2625
<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
2626
<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
2628
>>> class MyForm(Form):
2629
... default_field_1 = CharField()
2630
... default_field_2 = CharField()
2631
... def __init__(self, data=None, auto_id=False, field_list=[]):
2632
... Form.__init__(self, data, auto_id=auto_id)
2633
... for field in field_list:
2634
... self.fields[field[0]] = field[1]
2635
>>> field_list = [('field1', CharField()), ('field2', CharField())]
2636
>>> my_form = MyForm(field_list=field_list)
2638
<tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr>
2639
<tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr>
2640
<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
2641
<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr>
2642
>>> field_list = [('field3', CharField()), ('field4', CharField())]
2643
>>> my_form = MyForm(field_list=field_list)
2645
<tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr>
2646
<tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr>
2647
<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
2648
<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
2650
Similarly, changes to field attributes do not persist from one Form instance
2652
>>> class Person(Form):
2653
... first_name = CharField(required=False)
2654
... last_name = CharField(required=False)
2655
... def __init__(self, names_required=False, *args, **kwargs):
2656
... super(Person, self).__init__(*args, **kwargs)
2657
... if names_required:
2658
... self.fields['first_name'].required = True
2659
... self.fields['last_name'].required = True
2660
>>> f = Person(names_required=False)
2661
>>> f['first_name'].field.required, f['last_name'].field.required
2663
>>> f = Person(names_required=True)
2664
>>> f['first_name'].field.required, f['last_name'].field.required
2666
>>> f = Person(names_required=False)
2667
>>> f['first_name'].field.required, f['last_name'].field.required
2669
>>> class Person(Form):
2670
... first_name = CharField(max_length=30)
2671
... last_name = CharField(max_length=30)
2672
... def __init__(self, name_max_length=None, *args, **kwargs):
2673
... super(Person, self).__init__(*args, **kwargs)
2674
... if name_max_length:
2675
... self.fields['first_name'].max_length = name_max_length
2676
... self.fields['last_name'].max_length = name_max_length
2677
>>> f = Person(name_max_length=None)
2678
>>> f['first_name'].field.max_length, f['last_name'].field.max_length
2680
>>> f = Person(name_max_length=20)
2681
>>> f['first_name'].field.max_length, f['last_name'].field.max_length
2683
>>> f = Person(name_max_length=None)
2684
>>> f['first_name'].field.max_length, f['last_name'].field.max_length
2687
HiddenInput widgets are displayed differently in the as_table(), as_ul()
2688
and as_p() output of a Form -- their verbose names are not displayed, and a
2689
separate row is not displayed. They're displayed in the last row of the
2690
form, directly after that row's form element.
2691
>>> class Person(Form):
2692
... first_name = CharField()
2693
... last_name = CharField()
2694
... hidden_text = CharField(widget=HiddenInput)
2695
... birthday = DateField()
2696
>>> p = Person(auto_id=False)
2698
<tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr>
2699
<tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr>
2700
<tr><th>Birthday:</th><td><input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></td></tr>
2702
<li>First name: <input type="text" name="first_name" /></li>
2703
<li>Last name: <input type="text" name="last_name" /></li>
2704
<li>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></li>
2706
<p>First name: <input type="text" name="first_name" /></p>
2707
<p>Last name: <input type="text" name="last_name" /></p>
2708
<p>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></p>
2710
With auto_id set, a HiddenInput still gets an ID, but it doesn't get a label.
2711
>>> p = Person(auto_id='id_%s')
2713
<tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr>
2714
<tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr>
2715
<tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></td></tr>
2717
<li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li>
2718
<li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li>
2719
<li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></li>
2721
<p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p>
2722
<p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p>
2723
<p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /><input type="hidden" name="hidden_text" id="id_hidden_text" /></p>
2725
If a field with a HiddenInput has errors, the as_table() and as_ul() output
2726
will include the error message(s) with the text "(Hidden field [fieldname]) "
2727
prepended. This message is displayed at the top of the output, regardless of
2728
its field's order in the form.
2729
>>> p = Person({'first_name': 'John', 'last_name': 'Lennon', 'birthday': '1940-10-9'}, auto_id=False)
2731
<tr><td colspan="2"><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></td></tr>
2732
<tr><th>First name:</th><td><input type="text" name="first_name" value="John" /></td></tr>
2733
<tr><th>Last name:</th><td><input type="text" name="last_name" value="Lennon" /></td></tr>
2734
<tr><th>Birthday:</th><td><input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></td></tr>
2736
<li><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></li>
2737
<li>First name: <input type="text" name="first_name" value="John" /></li>
2738
<li>Last name: <input type="text" name="last_name" value="Lennon" /></li>
2739
<li>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></li>
2741
<ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul>
2742
<p>First name: <input type="text" name="first_name" value="John" /></p>
2743
<p>Last name: <input type="text" name="last_name" value="Lennon" /></p>
2744
<p>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></p>
2746
A corner case: It's possible for a form to have only HiddenInputs.
2747
>>> class TestForm(Form):
2748
... foo = CharField(widget=HiddenInput)
2749
... bar = CharField(widget=HiddenInput)
2750
>>> p = TestForm(auto_id=False)
2751
>>> print p.as_table()
2752
<input type="hidden" name="foo" /><input type="hidden" name="bar" />
2754
<input type="hidden" name="foo" /><input type="hidden" name="bar" />
2756
<input type="hidden" name="foo" /><input type="hidden" name="bar" />
2758
A Form's fields are displayed in the same order in which they were defined.
2759
>>> class TestForm(Form):
2760
... field1 = CharField()
2761
... field2 = CharField()
2762
... field3 = CharField()
2763
... field4 = CharField()
2764
... field5 = CharField()
2765
... field6 = CharField()
2766
... field7 = CharField()
2767
... field8 = CharField()
2768
... field9 = CharField()
2769
... field10 = CharField()
2770
... field11 = CharField()
2771
... field12 = CharField()
2772
... field13 = CharField()
2773
... field14 = CharField()
2774
>>> p = TestForm(auto_id=False)
2776
<tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr>
2777
<tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr>
2778
<tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr>
2779
<tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr>
2780
<tr><th>Field5:</th><td><input type="text" name="field5" /></td></tr>
2781
<tr><th>Field6:</th><td><input type="text" name="field6" /></td></tr>
2782
<tr><th>Field7:</th><td><input type="text" name="field7" /></td></tr>
2783
<tr><th>Field8:</th><td><input type="text" name="field8" /></td></tr>
2784
<tr><th>Field9:</th><td><input type="text" name="field9" /></td></tr>
2785
<tr><th>Field10:</th><td><input type="text" name="field10" /></td></tr>
2786
<tr><th>Field11:</th><td><input type="text" name="field11" /></td></tr>
2787
<tr><th>Field12:</th><td><input type="text" name="field12" /></td></tr>
2788
<tr><th>Field13:</th><td><input type="text" name="field13" /></td></tr>
2789
<tr><th>Field14:</th><td><input type="text" name="field14" /></td></tr>
2791
Some Field classes have an effect on the HTML attributes of their associated
2792
Widget. If you set max_length in a CharField and its associated widget is
2793
either a TextInput or PasswordInput, then the widget's rendered HTML will
2794
include the "maxlength" attribute.
2795
>>> class UserRegistration(Form):
2796
... username = CharField(max_length=10) # uses TextInput by default
2797
... password = CharField(max_length=10, widget=PasswordInput)
2798
... realname = CharField(max_length=10, widget=TextInput) # redundantly define widget, just to test
2799
... address = CharField() # no max_length defined here
2800
>>> p = UserRegistration(auto_id=False)
2802
<li>Username: <input type="text" name="username" maxlength="10" /></li>
2803
<li>Password: <input type="password" name="password" maxlength="10" /></li>
2804
<li>Realname: <input type="text" name="realname" maxlength="10" /></li>
2805
<li>Address: <input type="text" name="address" /></li>
2807
If you specify a custom "attrs" that includes the "maxlength" attribute,
2808
the Field's max_length attribute will override whatever "maxlength" you specify
2810
>>> class UserRegistration(Form):
2811
... username = CharField(max_length=10, widget=TextInput(attrs={'maxlength': 20}))
2812
... password = CharField(max_length=10, widget=PasswordInput)
2813
>>> p = UserRegistration(auto_id=False)
2815
<li>Username: <input type="text" name="username" maxlength="10" /></li>
2816
<li>Password: <input type="password" name="password" maxlength="10" /></li>
2818
# Specifying labels ###########################################################
2820
You can specify the label for a field by using the 'label' argument to a Field
2821
class. If you don't specify 'label', Django will use the field name with
2822
underscores converted to spaces, and the initial letter capitalized.
2823
>>> class UserRegistration(Form):
2824
... username = CharField(max_length=10, label='Your username')
2825
... password1 = CharField(widget=PasswordInput)
2826
... password2 = CharField(widget=PasswordInput, label='Password (again)')
2827
>>> p = UserRegistration(auto_id=False)
2829
<li>Your username: <input type="text" name="username" maxlength="10" /></li>
2830
<li>Password1: <input type="password" name="password1" /></li>
2831
<li>Password (again): <input type="password" name="password2" /></li>
2833
Labels for as_* methods will only end in a colon if they don't end in other
2834
punctuation already.
2835
>>> class Questions(Form):
2836
... q1 = CharField(label='The first question')
2837
... q2 = CharField(label='What is your name?')
2838
... q3 = CharField(label='The answer to life is:')
2839
... q4 = CharField(label='Answer this question!')
2840
... q5 = CharField(label='The last question. Period.')
2841
>>> print Questions(auto_id=False).as_p()
2842
<p>The first question: <input type="text" name="q1" /></p>
2843
<p>What is your name? <input type="text" name="q2" /></p>
2844
<p>The answer to life is: <input type="text" name="q3" /></p>
2845
<p>Answer this question! <input type="text" name="q4" /></p>
2846
<p>The last question. Period. <input type="text" name="q5" /></p>
2847
>>> print Questions().as_p()
2848
<p><label for="id_q1">The first question:</label> <input type="text" name="q1" id="id_q1" /></p>
2849
<p><label for="id_q2">What is your name?</label> <input type="text" name="q2" id="id_q2" /></p>
2850
<p><label for="id_q3">The answer to life is:</label> <input type="text" name="q3" id="id_q3" /></p>
2851
<p><label for="id_q4">Answer this question!</label> <input type="text" name="q4" id="id_q4" /></p>
2852
<p><label for="id_q5">The last question. Period.</label> <input type="text" name="q5" id="id_q5" /></p>
2854
A label can be a Unicode object or a bytestring with special characters.
2855
>>> class UserRegistration(Form):
2856
... username = CharField(max_length=10, label='ŠĐĆŽćžšđ')
2857
... password = CharField(widget=PasswordInput, label=u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111')
2858
>>> p = UserRegistration(auto_id=False)
2860
u'<li>\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111: <input type="text" name="username" maxlength="10" /></li>\n<li>\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111: <input type="password" name="password" /></li>'
2862
If a label is set to the empty string for a field, that field won't get a label.
2863
>>> class UserRegistration(Form):
2864
... username = CharField(max_length=10, label='')
2865
... password = CharField(widget=PasswordInput)
2866
>>> p = UserRegistration(auto_id=False)
2868
<li> <input type="text" name="username" maxlength="10" /></li>
2869
<li>Password: <input type="password" name="password" /></li>
2870
>>> p = UserRegistration(auto_id='id_%s')
2872
<li> <input id="id_username" type="text" name="username" maxlength="10" /></li>
2873
<li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li>
2875
If label is None, Django will auto-create the label from the field name. This
2876
is default behavior.
2877
>>> class UserRegistration(Form):
2878
... username = CharField(max_length=10, label=None)
2879
... password = CharField(widget=PasswordInput)
2880
>>> p = UserRegistration(auto_id=False)
2882
<li>Username: <input type="text" name="username" maxlength="10" /></li>
2883
<li>Password: <input type="password" name="password" /></li>
2884
>>> p = UserRegistration(auto_id='id_%s')
2886
<li><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></li>
2887
<li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li>
2889
# Initial data ################################################################
2891
You can specify initial data for a field by using the 'initial' argument to a
2892
Field class. This initial data is displayed when a Form is rendered with *no*
2893
data. It is not displayed when a Form is rendered with any data (including an
2894
empty dictionary). Also, the initial value is *not* used if data for a
2895
particular required field isn't provided.
2896
>>> class UserRegistration(Form):
2897
... username = CharField(max_length=10, initial='django')
2898
... password = CharField(widget=PasswordInput)
2900
Here, we're not submitting any data, so the initial value will be displayed.
2901
>>> p = UserRegistration(auto_id=False)
2903
<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
2904
<li>Password: <input type="password" name="password" /></li>
2906
Here, we're submitting data, so the initial value will *not* be displayed.
2907
>>> p = UserRegistration({}, auto_id=False)
2909
<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
2910
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
2911
>>> p = UserRegistration({'username': u''}, auto_id=False)
2913
<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
2914
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
2915
>>> p = UserRegistration({'username': u'foo'}, auto_id=False)
2917
<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
2918
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
2920
An 'initial' value is *not* used as a fallback if data is not provided. In this
2921
example, we don't provide a value for 'username', and the form raises a
2922
validation error rather than using the initial value for 'username'.
2923
>>> p = UserRegistration({'password': 'secret'})
2925
{'username': [u'This field is required.']}
2929
# Dynamic initial data ########################################################
2931
The previous technique dealt with "hard-coded" initial data, but it's also
2932
possible to specify initial data after you've already created the Form class
2933
(i.e., at runtime). Use the 'initial' parameter to the Form constructor. This
2934
should be a dictionary containing initial values for one or more fields in the
2935
form, keyed by field name.
2937
>>> class UserRegistration(Form):
2938
... username = CharField(max_length=10)
2939
... password = CharField(widget=PasswordInput)
2941
Here, we're not submitting any data, so the initial value will be displayed.
2942
>>> p = UserRegistration(initial={'username': 'django'}, auto_id=False)
2944
<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
2945
<li>Password: <input type="password" name="password" /></li>
2946
>>> p = UserRegistration(initial={'username': 'stephane'}, auto_id=False)
2948
<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
2949
<li>Password: <input type="password" name="password" /></li>
2951
The 'initial' parameter is meaningless if you pass data.
2952
>>> p = UserRegistration({}, initial={'username': 'django'}, auto_id=False)
2954
<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
2955
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
2956
>>> p = UserRegistration({'username': u''}, initial={'username': 'django'}, auto_id=False)
2958
<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
2959
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
2960
>>> p = UserRegistration({'username': u'foo'}, initial={'username': 'django'}, auto_id=False)
2962
<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
2963
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
2965
A dynamic 'initial' value is *not* used as a fallback if data is not provided.
2966
In this example, we don't provide a value for 'username', and the form raises a
2967
validation error rather than using the initial value for 'username'.
2968
>>> p = UserRegistration({'password': 'secret'}, initial={'username': 'django'})
2970
{'username': [u'This field is required.']}
2974
If a Form defines 'initial' *and* 'initial' is passed as a parameter to Form(),
2975
then the latter will get precedence.
2976
>>> class UserRegistration(Form):
2977
... username = CharField(max_length=10, initial='django')
2978
... password = CharField(widget=PasswordInput)
2979
>>> p = UserRegistration(initial={'username': 'babik'}, auto_id=False)
2981
<li>Username: <input type="text" name="username" value="babik" maxlength="10" /></li>
2982
<li>Password: <input type="password" name="password" /></li>
2984
# Callable initial data ########################################################
2986
The previous technique dealt with raw values as initial data, but it's also
2987
possible to specify callable data.
2989
>>> class UserRegistration(Form):
2990
... username = CharField(max_length=10)
2991
... password = CharField(widget=PasswordInput)
2993
We need to define functions that get called later.
2994
>>> def initial_django():
2996
>>> def initial_stephane():
2997
... return 'stephane'
2999
Here, we're not submitting any data, so the initial value will be displayed.
3000
>>> p = UserRegistration(initial={'username': initial_django}, auto_id=False)
3002
<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
3003
<li>Password: <input type="password" name="password" /></li>
3005
The 'initial' parameter is meaningless if you pass data.
3006
>>> p = UserRegistration({}, initial={'username': initial_django}, auto_id=False)
3008
<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
3009
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
3010
>>> p = UserRegistration({'username': u''}, initial={'username': initial_django}, auto_id=False)
3012
<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
3013
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
3014
>>> p = UserRegistration({'username': u'foo'}, initial={'username': initial_django}, auto_id=False)
3016
<li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li>
3017
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li>
3019
A callable 'initial' value is *not* used as a fallback if data is not provided.
3020
In this example, we don't provide a value for 'username', and the form raises a
3021
validation error rather than using the initial value for 'username'.
3022
>>> p = UserRegistration({'password': 'secret'}, initial={'username': initial_django})
3024
{'username': [u'This field is required.']}
3028
If a Form defines 'initial' *and* 'initial' is passed as a parameter to Form(),
3029
then the latter will get precedence.
3030
>>> class UserRegistration(Form):
3031
... username = CharField(max_length=10, initial=initial_django)
3032
... password = CharField(widget=PasswordInput)
3033
>>> p = UserRegistration(auto_id=False)
3035
<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
3036
<li>Password: <input type="password" name="password" /></li>
3037
>>> p = UserRegistration(initial={'username': initial_stephane}, auto_id=False)
3039
<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
3040
<li>Password: <input type="password" name="password" /></li>
3042
# Help text ###################################################################
3044
You can specify descriptive text for a field by using the 'help_text' argument
3045
to a Field class. This help text is displayed when a Form is rendered.
3046
>>> class UserRegistration(Form):
3047
... username = CharField(max_length=10, help_text='e.g., user@example.com')
3048
... password = CharField(widget=PasswordInput, help_text='Choose wisely.')
3049
>>> p = UserRegistration(auto_id=False)
3051
<li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li>
3052
<li>Password: <input type="password" name="password" /> Choose wisely.</li>
3054
<p>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</p>
3055
<p>Password: <input type="password" name="password" /> Choose wisely.</p>
3056
>>> print p.as_table()
3057
<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /><br />e.g., user@example.com</td></tr>
3058
<tr><th>Password:</th><td><input type="password" name="password" /><br />Choose wisely.</td></tr>
3060
The help text is displayed whether or not data is provided for the form.
3061
>>> p = UserRegistration({'username': u'foo'}, auto_id=False)
3063
<li>Username: <input type="text" name="username" value="foo" maxlength="10" /> e.g., user@example.com</li>
3064
<li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> Choose wisely.</li>
3066
help_text is not displayed for hidden fields. It can be used for documentation
3068
>>> class UserRegistration(Form):
3069
... username = CharField(max_length=10, help_text='e.g., user@example.com')
3070
... password = CharField(widget=PasswordInput)
3071
... next = CharField(widget=HiddenInput, initial='/', help_text='Redirect destination')
3072
>>> p = UserRegistration(auto_id=False)
3074
<li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li>
3075
<li>Password: <input type="password" name="password" /><input type="hidden" name="next" value="/" /></li>
3077
Help text can include arbitrary Unicode characters.
3078
>>> class UserRegistration(Form):
3079
... username = CharField(max_length=10, help_text='ŠĐĆŽćžšđ')
3080
>>> p = UserRegistration(auto_id=False)
3082
u'<li>Username: <input type="text" name="username" maxlength="10" /> \u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</li>'
3084
# Subclassing forms ###########################################################
3086
You can subclass a Form to add fields. The resulting form subclass will have
3087
all of the fields of the parent Form, plus whichever fields you define in the
3089
>>> class Person(Form):
3090
... first_name = CharField()
3091
... last_name = CharField()
3092
... birthday = DateField()
3093
>>> class Musician(Person):
3094
... instrument = CharField()
3095
>>> p = Person(auto_id=False)
3097
<li>First name: <input type="text" name="first_name" /></li>
3098
<li>Last name: <input type="text" name="last_name" /></li>
3099
<li>Birthday: <input type="text" name="birthday" /></li>
3100
>>> m = Musician(auto_id=False)
3102
<li>First name: <input type="text" name="first_name" /></li>
3103
<li>Last name: <input type="text" name="last_name" /></li>
3104
<li>Birthday: <input type="text" name="birthday" /></li>
3105
<li>Instrument: <input type="text" name="instrument" /></li>
3107
Yes, you can subclass multiple forms. The fields are added in the order in
3108
which the parent classes are listed.
3109
>>> class Person(Form):
3110
... first_name = CharField()
3111
... last_name = CharField()
3112
... birthday = DateField()
3113
>>> class Instrument(Form):
3114
... instrument = CharField()
3115
>>> class Beatle(Person, Instrument):
3116
... haircut_type = CharField()
3117
>>> b = Beatle(auto_id=False)
3119
<li>First name: <input type="text" name="first_name" /></li>
3120
<li>Last name: <input type="text" name="last_name" /></li>
3121
<li>Birthday: <input type="text" name="birthday" /></li>
3122
<li>Instrument: <input type="text" name="instrument" /></li>
3123
<li>Haircut type: <input type="text" name="haircut_type" /></li>
3125
# Forms with prefixes #########################################################
3127
Sometimes it's necessary to have multiple forms display on the same HTML page,
3128
or multiple copies of the same form. We can accomplish this with form prefixes.
3129
Pass the keyword argument 'prefix' to the Form constructor to use this feature.
3130
This value will be prepended to each HTML form field name. One way to think
3131
about this is "namespaces for HTML forms". Notice that in the data argument,
3132
each field's key has the prefix, in this case 'person1', prepended to the
3134
>>> class Person(Form):
3135
... first_name = CharField()
3136
... last_name = CharField()
3137
... birthday = DateField()
3139
... 'person1-first_name': u'John',
3140
... 'person1-last_name': u'Lennon',
3141
... 'person1-birthday': u'1940-10-9'
3143
>>> p = Person(data, prefix='person1')
3145
<li><label for="id_person1-first_name">First name:</label> <input type="text" name="person1-first_name" value="John" id="id_person1-first_name" /></li>
3146
<li><label for="id_person1-last_name">Last name:</label> <input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" /></li>
3147
<li><label for="id_person1-birthday">Birthday:</label> <input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /></li>
3148
>>> print p['first_name']
3149
<input type="text" name="person1-first_name" value="John" id="id_person1-first_name" />
3150
>>> print p['last_name']
3151
<input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" />
3152
>>> print p['birthday']
3153
<input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" />
3159
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
3161
Let's try submitting some bad data to make sure form.errors and field.errors
3164
... 'person1-first_name': u'',
3165
... 'person1-last_name': u'',
3166
... 'person1-birthday': u''
3168
>>> p = Person(data, prefix='person1')
3170
{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']}
3171
>>> p['first_name'].errors
3172
[u'This field is required.']
3173
>>> p['person1-first_name'].errors
3174
Traceback (most recent call last):
3176
KeyError: "Key 'person1-first_name' not found in Form"
3178
In this example, the data doesn't have a prefix, but the form requires it, so
3179
the form doesn't "see" the fields.
3181
... 'first_name': u'John',
3182
... 'last_name': u'Lennon',
3183
... 'birthday': u'1940-10-9'
3185
>>> p = Person(data, prefix='person1')
3187
{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']}
3189
With prefixes, a single data dictionary can hold data for multiple instances
3192
... 'person1-first_name': u'John',
3193
... 'person1-last_name': u'Lennon',
3194
... 'person1-birthday': u'1940-10-9',
3195
... 'person2-first_name': u'Jim',
3196
... 'person2-last_name': u'Morrison',
3197
... 'person2-birthday': u'1943-12-8'
3199
>>> p1 = Person(data, prefix='person1')
3203
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
3204
>>> p2 = Person(data, prefix='person2')
3208
{'first_name': u'Jim', 'last_name': u'Morrison', 'birthday': datetime.date(1943, 12, 8)}
3210
By default, forms append a hyphen between the prefix and the field name, but a
3211
form can alter that behavior by implementing the add_prefix() method. This
3212
method takes a field name and returns the prefixed field, according to
3214
>>> class Person(Form):
3215
... first_name = CharField()
3216
... last_name = CharField()
3217
... birthday = DateField()
3218
... def add_prefix(self, field_name):
3219
... return self.prefix and '%s-prefix-%s' % (self.prefix, field_name) or field_name
3220
>>> p = Person(prefix='foo')
3222
<li><label for="id_foo-prefix-first_name">First name:</label> <input type="text" name="foo-prefix-first_name" id="id_foo-prefix-first_name" /></li>
3223
<li><label for="id_foo-prefix-last_name">Last name:</label> <input type="text" name="foo-prefix-last_name" id="id_foo-prefix-last_name" /></li>
3224
<li><label for="id_foo-prefix-birthday">Birthday:</label> <input type="text" name="foo-prefix-birthday" id="id_foo-prefix-birthday" /></li>
3226
... 'foo-prefix-first_name': u'John',
3227
... 'foo-prefix-last_name': u'Lennon',
3228
... 'foo-prefix-birthday': u'1940-10-9'
3230
>>> p = Person(data, prefix='foo')
3234
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
3236
# Forms with NullBooleanFields ################################################
3238
NullBooleanField is a bit of a special case because its presentation (widget)
3239
is different than its data. This is handled transparently, though.
3241
>>> class Person(Form):
3242
... name = CharField()
3243
... is_cool = NullBooleanField()
3244
>>> p = Person({'name': u'Joe'}, auto_id=False)
3245
>>> print p['is_cool']
3246
<select name="is_cool">
3247
<option value="1" selected="selected">Unknown</option>
3248
<option value="2">Yes</option>
3249
<option value="3">No</option>
3251
>>> p = Person({'name': u'Joe', 'is_cool': u'1'}, auto_id=False)
3252
>>> print p['is_cool']
3253
<select name="is_cool">
3254
<option value="1" selected="selected">Unknown</option>
3255
<option value="2">Yes</option>
3256
<option value="3">No</option>
3258
>>> p = Person({'name': u'Joe', 'is_cool': u'2'}, auto_id=False)
3259
>>> print p['is_cool']
3260
<select name="is_cool">
3261
<option value="1">Unknown</option>
3262
<option value="2" selected="selected">Yes</option>
3263
<option value="3">No</option>
3265
>>> p = Person({'name': u'Joe', 'is_cool': u'3'}, auto_id=False)
3266
>>> print p['is_cool']
3267
<select name="is_cool">
3268
<option value="1">Unknown</option>
3269
<option value="2">Yes</option>
3270
<option value="3" selected="selected">No</option>
3272
>>> p = Person({'name': u'Joe', 'is_cool': True}, auto_id=False)
3273
>>> print p['is_cool']
3274
<select name="is_cool">
3275
<option value="1">Unknown</option>
3276
<option value="2" selected="selected">Yes</option>
3277
<option value="3">No</option>
3279
>>> p = Person({'name': u'Joe', 'is_cool': False}, auto_id=False)
3280
>>> print p['is_cool']
3281
<select name="is_cool">
3282
<option value="1">Unknown</option>
3283
<option value="2">Yes</option>
3284
<option value="3" selected="selected">No</option>
3287
# Forms with FileFields ################################################
3289
FileFields are a special case because they take their data from the request.FILES,
3292
>>> class FileForm(Form):
3293
... file1 = FileField()
3294
>>> f = FileForm(auto_id=False)
3296
<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>
3298
>>> f = FileForm(data={}, files={}, auto_id=False)
3300
<tr><th>File1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="file" name="file1" /></td></tr>
3302
>>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':''}}, auto_id=False)
3304
<tr><th>File1:</th><td><ul class="errorlist"><li>The submitted file is empty.</li></ul><input type="file" name="file1" /></td></tr>
3306
>>> f = FileForm(data={}, files={'file1': 'something that is not a file'}, auto_id=False)
3308
<tr><th>File1:</th><td><ul class="errorlist"><li>No file was submitted. Check the encoding type on the form.</li></ul><input type="file" name="file1" /></td></tr>
3310
>>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':'some content'}}, auto_id=False)
3312
<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>
3316
# Basic form processing in a view #############################################
3318
>>> from django.template import Template, Context
3319
>>> class UserRegistration(Form):
3320
... username = CharField(max_length=10)
3321
... password1 = CharField(widget=PasswordInput)
3322
... password2 = CharField(widget=PasswordInput)
3323
... def clean(self):
3324
... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']:
3325
... raise ValidationError(u'Please make sure your passwords match.')
3326
... return self.cleaned_data
3327
>>> def my_function(method, post_data):
3328
... if method == 'POST':
3329
... form = UserRegistration(post_data, auto_id=False)
3331
... form = UserRegistration(auto_id=False)
3332
... if form.is_valid():
3333
... return 'VALID: %r' % form.cleaned_data
3334
... t = Template('<form action="" method="post">\n<table>\n{{ form }}\n</table>\n<input type="submit" />\n</form>')
3335
... return t.render(Context({'form': form}))
3337
Case 1: GET (an empty form, with no errors).
3338
>>> print my_function('GET', {})
3339
<form action="" method="post">
3341
<tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /></td></tr>
3342
<tr><th>Password1:</th><td><input type="password" name="password1" /></td></tr>
3343
<tr><th>Password2:</th><td><input type="password" name="password2" /></td></tr>
3345
<input type="submit" />
3348
Case 2: POST with erroneous data (a redisplayed form, with errors).
3349
>>> print my_function('POST', {'username': 'this-is-a-long-username', 'password1': 'foo', 'password2': 'bar'})
3350
<form action="" method="post">
3352
<tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr>
3353
<tr><th>Username:</th><td><ul class="errorlist"><li>Ensure this value has at most 10 characters (it has 23).</li></ul><input type="text" name="username" value="this-is-a-long-username" maxlength="10" /></td></tr>
3354
<tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr>
3355
<tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr>
3357
<input type="submit" />
3360
Case 3: POST with valid data (the success message).
3361
>>> print my_function('POST', {'username': 'adrian', 'password1': 'secret', 'password2': 'secret'})
3362
VALID: {'username': u'adrian', 'password1': u'secret', 'password2': u'secret'}
3364
# Some ideas for using templates with forms ###################################
3366
>>> class UserRegistration(Form):
3367
... username = CharField(max_length=10, help_text="Good luck picking a username that doesn't already exist.")
3368
... password1 = CharField(widget=PasswordInput)
3369
... password2 = CharField(widget=PasswordInput)
3370
... def clean(self):
3371
... if self.cleaned_data.get('password1') and self.cleaned_data.get('password2') and self.cleaned_data['password1'] != self.cleaned_data['password2']:
3372
... raise ValidationError(u'Please make sure your passwords match.')
3373
... return self.cleaned_data
3375
You have full flexibility in displaying form fields in a template. Just pass a
3376
Form instance to the template, and use "dot" access to refer to individual
3377
fields. Note, however, that this flexibility comes with the responsibility of
3378
displaying all the errors, including any that might not be associated with a
3380
>>> t = Template('''<form action="">
3381
... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p>
3382
... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p>
3383
... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p>
3384
... <input type="submit" />
3386
>>> print t.render(Context({'form': UserRegistration(auto_id=False)}))
3388
<p><label>Your username: <input type="text" name="username" maxlength="10" /></label></p>
3389
<p><label>Password: <input type="password" name="password1" /></label></p>
3390
<p><label>Password (again): <input type="password" name="password2" /></label></p>
3391
<input type="submit" />
3393
>>> print t.render(Context({'form': UserRegistration({'username': 'django'}, auto_id=False)}))
3395
<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p>
3396
<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password: <input type="password" name="password1" /></label></p>
3397
<ul class="errorlist"><li>This field is required.</li></ul><p><label>Password (again): <input type="password" name="password2" /></label></p>
3398
<input type="submit" />
3401
Use form.[field].label to output a field's label. You can specify the label for
3402
a field by using the 'label' argument to a Field class. If you don't specify
3403
'label', Django will use the field name with underscores converted to spaces,
3404
and the initial letter capitalized.
3405
>>> t = Template('''<form action="">
3406
... <p><label>{{ form.username.label }}: {{ form.username }}</label></p>
3407
... <p><label>{{ form.password1.label }}: {{ form.password1 }}</label></p>
3408
... <p><label>{{ form.password2.label }}: {{ form.password2 }}</label></p>
3409
... <input type="submit" />
3411
>>> print t.render(Context({'form': UserRegistration(auto_id=False)}))
3413
<p><label>Username: <input type="text" name="username" maxlength="10" /></label></p>
3414
<p><label>Password1: <input type="password" name="password1" /></label></p>
3415
<p><label>Password2: <input type="password" name="password2" /></label></p>
3416
<input type="submit" />
3419
User form.[field].label_tag to output a field's label with a <label> tag
3420
wrapped around it, but *only* if the given field has an "id" attribute.
3421
Recall from above that passing the "auto_id" argument to a Form gives each
3422
field an "id" attribute.
3423
>>> t = Template('''<form action="">
3424
... <p>{{ form.username.label_tag }}: {{ form.username }}</p>
3425
... <p>{{ form.password1.label_tag }}: {{ form.password1 }}</p>
3426
... <p>{{ form.password2.label_tag }}: {{ form.password2 }}</p>
3427
... <input type="submit" />
3429
>>> print t.render(Context({'form': UserRegistration(auto_id=False)}))
3431
<p>Username: <input type="text" name="username" maxlength="10" /></p>
3432
<p>Password1: <input type="password" name="password1" /></p>
3433
<p>Password2: <input type="password" name="password2" /></p>
3434
<input type="submit" />
3436
>>> print t.render(Context({'form': UserRegistration(auto_id='id_%s')}))
3438
<p><label for="id_username">Username</label>: <input id="id_username" type="text" name="username" maxlength="10" /></p>
3439
<p><label for="id_password1">Password1</label>: <input type="password" name="password1" id="id_password1" /></p>
3440
<p><label for="id_password2">Password2</label>: <input type="password" name="password2" id="id_password2" /></p>
3441
<input type="submit" />
3444
User form.[field].help_text to output a field's help text. If the given field
3445
does not have help text, nothing will be output.
3446
>>> t = Template('''<form action="">
3447
... <p>{{ form.username.label_tag }}: {{ form.username }}<br />{{ form.username.help_text }}</p>
3448
... <p>{{ form.password1.label_tag }}: {{ form.password1 }}</p>
3449
... <p>{{ form.password2.label_tag }}: {{ form.password2 }}</p>
3450
... <input type="submit" />
3452
>>> print t.render(Context({'form': UserRegistration(auto_id=False)}))
3454
<p>Username: <input type="text" name="username" maxlength="10" /><br />Good luck picking a username that doesn't already exist.</p>
3455
<p>Password1: <input type="password" name="password1" /></p>
3456
<p>Password2: <input type="password" name="password2" /></p>
3457
<input type="submit" />
3459
>>> Template('{{ form.password1.help_text }}').render(Context({'form': UserRegistration(auto_id=False)}))
3462
The label_tag() method takes an optional attrs argument: a dictionary of HTML
3463
attributes to add to the <label> tag.
3464
>>> f = UserRegistration(auto_id='id_%s')
3466
... print bf.label_tag(attrs={'class': 'pretty'})
3467
<label for="id_username" class="pretty">Username</label>
3468
<label for="id_password1" class="pretty">Password1</label>
3469
<label for="id_password2" class="pretty">Password2</label>
3471
To display the errors that aren't associated with a particular field -- e.g.,
3472
the errors caused by Form.clean() -- use {{ form.non_field_errors }} in the
3473
template. If used on its own, it is displayed as a <ul> (or an empty string, if
3474
the list of errors is empty). You can also use it in {% if %} statements.
3475
>>> t = Template('''<form action="">
3476
... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p>
3477
... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p>
3478
... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p>
3479
... <input type="submit" />
3481
>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)}))
3483
<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p>
3484
<p><label>Password: <input type="password" name="password1" value="foo" /></label></p>
3485
<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p>
3486
<input type="submit" />
3488
>>> t = Template('''<form action="">
3489
... {{ form.non_field_errors }}
3490
... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p>
3491
... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p>
3492
... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p>
3493
... <input type="submit" />
3495
>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)}))
3497
<ul class="errorlist"><li>Please make sure your passwords match.</li></ul>
3498
<p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p>
3499
<p><label>Password: <input type="password" name="password1" value="foo" /></label></p>
3500
<p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p>
3501
<input type="submit" />
3508
The newforms library comes with some extra, higher-level Field and Widget
3509
classes that demonstrate some of the library's abilities.
3511
# SelectDateWidget ############################################################
3513
>>> from django.newforms.extras import SelectDateWidget
3514
>>> w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016'))
3515
>>> print w.render('mydate', '')
3516
<select name="mydate_month">
3517
<option value="1">January</option>
3518
<option value="2">February</option>
3519
<option value="3">March</option>
3520
<option value="4">April</option>
3521
<option value="5">May</option>
3522
<option value="6">June</option>
3523
<option value="7">July</option>
3524
<option value="8">August</option>
3525
<option value="9">September</option>
3526
<option value="10">October</option>
3527
<option value="11">November</option>
3528
<option value="12">December</option>
3530
<select name="mydate_day">
3531
<option value="1">1</option>
3532
<option value="2">2</option>
3533
<option value="3">3</option>
3534
<option value="4">4</option>
3535
<option value="5">5</option>
3536
<option value="6">6</option>
3537
<option value="7">7</option>
3538
<option value="8">8</option>
3539
<option value="9">9</option>
3540
<option value="10">10</option>
3541
<option value="11">11</option>
3542
<option value="12">12</option>
3543
<option value="13">13</option>
3544
<option value="14">14</option>
3545
<option value="15">15</option>
3546
<option value="16">16</option>
3547
<option value="17">17</option>
3548
<option value="18">18</option>
3549
<option value="19">19</option>
3550
<option value="20">20</option>
3551
<option value="21">21</option>
3552
<option value="22">22</option>
3553
<option value="23">23</option>
3554
<option value="24">24</option>
3555
<option value="25">25</option>
3556
<option value="26">26</option>
3557
<option value="27">27</option>
3558
<option value="28">28</option>
3559
<option value="29">29</option>
3560
<option value="30">30</option>
3561
<option value="31">31</option>
3563
<select name="mydate_year">
3564
<option value="2007">2007</option>
3565
<option value="2008">2008</option>
3566
<option value="2009">2009</option>
3567
<option value="2010">2010</option>
3568
<option value="2011">2011</option>
3569
<option value="2012">2012</option>
3570
<option value="2013">2013</option>
3571
<option value="2014">2014</option>
3572
<option value="2015">2015</option>
3573
<option value="2016">2016</option>
3575
>>> w.render('mydate', None) == w.render('mydate', '')
3577
>>> print w.render('mydate', '2010-04-15')
3578
<select name="mydate_month">
3579
<option value="1">January</option>
3580
<option value="2">February</option>
3581
<option value="3">March</option>
3582
<option value="4" selected="selected">April</option>
3583
<option value="5">May</option>
3584
<option value="6">June</option>
3585
<option value="7">July</option>
3586
<option value="8">August</option>
3587
<option value="9">September</option>
3588
<option value="10">October</option>
3589
<option value="11">November</option>
3590
<option value="12">December</option>
3592
<select name="mydate_day">
3593
<option value="1">1</option>
3594
<option value="2">2</option>
3595
<option value="3">3</option>
3596
<option value="4">4</option>
3597
<option value="5">5</option>
3598
<option value="6">6</option>
3599
<option value="7">7</option>
3600
<option value="8">8</option>
3601
<option value="9">9</option>
3602
<option value="10">10</option>
3603
<option value="11">11</option>
3604
<option value="12">12</option>
3605
<option value="13">13</option>
3606
<option value="14">14</option>
3607
<option value="15" selected="selected">15</option>
3608
<option value="16">16</option>
3609
<option value="17">17</option>
3610
<option value="18">18</option>
3611
<option value="19">19</option>
3612
<option value="20">20</option>
3613
<option value="21">21</option>
3614
<option value="22">22</option>
3615
<option value="23">23</option>
3616
<option value="24">24</option>
3617
<option value="25">25</option>
3618
<option value="26">26</option>
3619
<option value="27">27</option>
3620
<option value="28">28</option>
3621
<option value="29">29</option>
3622
<option value="30">30</option>
3623
<option value="31">31</option>
3625
<select name="mydate_year">
3626
<option value="2007">2007</option>
3627
<option value="2008">2008</option>
3628
<option value="2009">2009</option>
3629
<option value="2010" selected="selected">2010</option>
3630
<option value="2011">2011</option>
3631
<option value="2012">2012</option>
3632
<option value="2013">2013</option>
3633
<option value="2014">2014</option>
3634
<option value="2015">2015</option>
3635
<option value="2016">2016</option>
3638
Using a SelectDateWidget in a form:
3640
>>> class GetDate(Form):
3641
... mydate = DateField(widget=SelectDateWidget)
3642
>>> a = GetDate({'mydate_month':'4', 'mydate_day':'1', 'mydate_year':'2008'})
3643
>>> print a.is_valid()
3645
>>> print a.cleaned_data['mydate']
3648
As with any widget that implements get_value_from_datadict,
3649
we must be prepared to accept the input from the "as_hidden"
3652
>>> print a['mydate'].as_hidden()
3653
<input type="hidden" name="mydate" value="2008-4-1" id="id_mydate" />
3654
>>> b=GetDate({'mydate':'2008-4-1'})
3655
>>> print b.is_valid()
3657
>>> print b.cleaned_data['mydate']
3661
# MultiWidget and MultiValueField #############################################
3662
# MultiWidgets are widgets composed of other widgets. They are usually
3663
# combined with MultiValueFields - a field that is composed of other fields.
3664
# MulitWidgets can themselved be composed of other MultiWidgets.
3665
# SplitDateTimeWidget is one example of a MultiWidget.
3667
>>> class ComplexMultiWidget(MultiWidget):
3668
... def __init__(self, attrs=None):
3671
... SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
3672
... SplitDateTimeWidget(),
3674
... super(ComplexMultiWidget, self).__init__(widgets, attrs)
3676
... def decompress(self, value):
3678
... data = value.split(',')
3679
... return [data[0], data[1], datetime.datetime(*time.strptime(data[2], "%Y-%m-%d %H:%M:%S")[0:6])]
3680
... return [None, None, None]
3681
... def format_output(self, rendered_widgets):
3682
... return u'\n'.join(rendered_widgets)
3683
>>> w = ComplexMultiWidget()
3684
>>> print w.render('name', 'some text,JP,2007-04-25 06:24:00')
3685
<input type="text" name="name_0" value="some text" />
3686
<select multiple="multiple" name="name_1">
3687
<option value="J" selected="selected">John</option>
3688
<option value="P" selected="selected">Paul</option>
3689
<option value="G">George</option>
3690
<option value="R">Ringo</option>
3692
<input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" />
3694
>>> class ComplexField(MultiValueField):
3695
... def __init__(self, required=True, widget=None, label=None, initial=None):
3698
... MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
3699
... SplitDateTimeField()
3701
... super(ComplexField, self).__init__(fields, required, widget, label, initial)
3703
... def compress(self, data_list):
3705
... return '%s,%s,%s' % (data_list[0],''.join(data_list[1]),data_list[2])
3708
>>> f = ComplexField(widget=w)
3709
>>> f.clean(['some text', ['J','P'], ['2007-04-25','6:24:00']])
3710
u'some text,JP,2007-04-25 06:24:00'
3711
>>> f.clean(['some text',['X'], ['2007-04-25','6:24:00']])
3712
Traceback (most recent call last):
3714
ValidationError: [u'Select a valid choice. X is not one of the available choices.']
3716
# If insufficient data is provided, None is substituted
3717
>>> f.clean(['some text',['JP']])
3718
Traceback (most recent call last):
3720
ValidationError: [u'This field is required.']
3722
>>> class ComplexFieldForm(Form):
3723
... field1 = ComplexField(widget=w)
3724
>>> f = ComplexFieldForm()
3726
<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" id="id_field1_0" />
3727
<select multiple="multiple" name="field1_1" id="id_field1_1">
3728
<option value="J">John</option>
3729
<option value="P">Paul</option>
3730
<option value="G">George</option>
3731
<option value="R">Ringo</option>
3733
<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>
3735
>>> f = ComplexFieldForm({'field1_0':'some text','field1_1':['J','P'], 'field1_2_0':'2007-04-25', 'field1_2_1':'06:24:00'})
3737
<tr><th><label for="id_field1_0">Field1:</label></th><td><input type="text" name="field1_0" value="some text" id="id_field1_0" />
3738
<select multiple="multiple" name="field1_1" id="id_field1_1">
3739
<option value="J" selected="selected">John</option>
3740
<option value="P" selected="selected">Paul</option>
3741
<option value="G">George</option>
3742
<option value="R">Ringo</option>
3744
<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>
3747
{'field1': u'some text,JP,2007-04-25 06:24:00'}
3749
#################################
3750
# Tests of underlying functions #
3751
#################################
3753
# smart_unicode tests
3754
>>> from django.utils.encoding import smart_unicode
3756
... def __str__(self):
3757
... return 'ŠĐĆŽćžšđ'
3759
... def __str__(self):
3761
... def __unicode__(self):
3762
... return u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
3763
>>> smart_unicode(Test())
3764
u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
3765
>>> smart_unicode(TestU())
3766
u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111'
3767
>>> smart_unicode(1)
3769
>>> smart_unicode('foo')
3773
>>> from django.newforms.util import flatatt
3774
>>> flatatt({'id': "header"})
3776
>>> flatatt({'class': "news", 'title': "Read this"})
3777
u' class="news" title="Read this"'
3781
####################################
3782
# Test accessing errors in clean() #
3783
####################################
3785
>>> class UserForm(Form):
3786
... username = CharField(max_length=10)
3787
... password = CharField(widget=PasswordInput)
3788
... def clean(self):
3789
... data = self.cleaned_data
3790
... if not self.errors:
3791
... data['username'] = data['username'].lower()
3794
>>> f = UserForm({'username': 'SirRobin', 'password': 'blue'})
3797
>>> f.cleaned_data['username']
2
from extra import tests as extra_tests
3
from fields import tests as fields_tests
4
from forms import tests as form_tests
5
from error_messages import tests as custom_error_message_tests
6
from localflavor.ar import tests as localflavor_ar_tests
7
from localflavor.au import tests as localflavor_au_tests
8
from localflavor.br import tests as localflavor_br_tests
9
from localflavor.ca import tests as localflavor_ca_tests
10
from localflavor.ch import tests as localflavor_ch_tests
11
from localflavor.cl import tests as localflavor_cl_tests
12
from localflavor.de import tests as localflavor_de_tests
13
from localflavor.es import tests as localflavor_es_tests
14
from localflavor.fi import tests as localflavor_fi_tests
15
from localflavor.fr import tests as localflavor_fr_tests
16
from localflavor.generic import tests as localflavor_generic_tests
17
from localflavor.is_ import tests as localflavor_is_tests
18
from localflavor.it import tests as localflavor_it_tests
19
from localflavor.jp import tests as localflavor_jp_tests
20
from localflavor.nl import tests as localflavor_nl_tests
21
from localflavor.pl import tests as localflavor_pl_tests
22
from localflavor.sk import tests as localflavor_sk_tests
23
from localflavor.uk import tests as localflavor_uk_tests
24
from localflavor.us import tests as localflavor_us_tests
25
from regressions import tests as regression_tests
26
from util import tests as util_tests
27
from widgets import tests as widgets_tests
30
'extra_tests': extra_tests,
31
'fields_tests': fields_tests,
3802
32
'form_tests': form_tests,
3803
'localflavor': localflavor_tests,
3804
'regressions': regression_tests,
33
'custom_error_message_tests': custom_error_message_tests,
34
'localflavor_ar_tests': localflavor_ar_tests,
35
'localflavor_au_tests': localflavor_au_tests,
36
'localflavor_br_tests': localflavor_br_tests,
37
'localflavor_ca_tests': localflavor_ca_tests,
38
'localflavor_ch_tests': localflavor_ch_tests,
39
'localflavor_cl_tests': localflavor_cl_tests,
40
'localflavor_de_tests': localflavor_de_tests,
41
'localflavor_es_tests': localflavor_es_tests,
42
'localflavor_fi_tests': localflavor_fi_tests,
43
'localflavor_fr_tests': localflavor_fr_tests,
44
'localflavor_generic_tests': localflavor_generic_tests,
45
'localflavor_is_tests': localflavor_is_tests,
46
'localflavor_it_tests': localflavor_it_tests,
47
'localflavor_jp_tests': localflavor_jp_tests,
48
'localflavor_nl_tests': localflavor_nl_tests,
49
'localflavor_pl_tests': localflavor_pl_tests,
50
'localflavor_sk_tests': localflavor_sk_tests,
51
'localflavor_uk_tests': localflavor_uk_tests,
52
'localflavor_us_tests': localflavor_us_tests,
53
'regressions_tests': regression_tests,
54
'util_tests': util_tests,
55
'widgets_tests': widgets_tests,
3807
58
if __name__ == "__main__":