~gary-wilson/django/cache-reorg

« back to all changes in this revision

Viewing changes to tests/regressiontests/forms/tests.py

  • Committer: Gary Wilson
  • Date: 2007-10-28 22:17:58 UTC
  • mfrom: (3786.1.415)
  • Revision ID: gary.wilson@gmail.com-20071028221758-jq4dxnf6idol3ioo
Merged upstream changes.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
# -*- coding: utf-8 -*-
2
 
from localflavor import localflavor_tests
3
 
from regressions import regression_tests
4
 
 
5
 
form_tests = r"""
6
 
>>> from django.newforms import *
7
 
>>> from django.newforms.widgets import RadioFieldRenderer
8
 
>>> import datetime
9
 
>>> import time
10
 
>>> import re
11
 
>>> try:
12
 
...     from decimal import Decimal
13
 
... except ImportError:
14
 
...     from django.utils._decimal import Decimal
15
 
 
16
 
###########
17
 
# Widgets #
18
 
###########
19
 
 
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
22
 
validation.
23
 
 
24
 
# TextInput Widget ############################################################
25
 
 
26
 
>>> w = TextInput()
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 &quot;quoted&quot; &amp; 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" />'
37
 
 
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" />'
42
 
 
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" />'
49
 
 
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" />'
54
 
 
55
 
# PasswordInput Widget ############################################################
56
 
 
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 &quot;quoted&quot; &amp; 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" />'
68
 
 
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" />'
75
 
 
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" />'
80
 
 
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" />'
83
 
 
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" />'
99
 
 
100
 
# HiddenInput Widget ############################################################
101
 
 
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 &quot;quoted&quot; &amp; 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" />'
113
 
 
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" />'
120
 
 
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" />'
125
 
 
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" />'
128
 
 
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" />'
133
 
 
134
 
# MultipleHiddenInput Widget ##################################################
135
 
 
136
 
>>> w = MultipleHiddenInput()
137
 
>>> w.render('email', [])
138
 
u''
139
 
>>> w.render('email', None)
140
 
u''
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 &quot;quoted&quot; &amp; 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" />'
151
 
 
152
 
You can also pass 'attrs' to the constructor:
153
 
>>> w = MultipleHiddenInput(attrs={'class': 'fun'})
154
 
>>> w.render('email', [])
155
 
u''
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" />'
160
 
 
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" />'
165
 
 
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" />'
168
 
 
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" />'
173
 
 
174
 
# FileInput Widget ############################################################
175
 
 
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.
178
 
>>> w = FileInput()
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" />'
189
 
 
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" />'
196
 
 
197
 
>>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})
198
 
u'<input type="file" class="fun" name="email" />'
199
 
 
200
 
# Textarea Widget #############################################################
201
 
 
202
 
>>> w = Textarea()
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 &quot;quoted&quot; &amp; 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>'
213
 
 
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>'
220
 
 
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>'
225
 
 
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>'
228
 
 
229
 
# CheckboxInput Widget ########################################################
230
 
 
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" />'
240
 
 
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" />'
245
 
 
246
 
>>> w.render('is_cool', False, attrs={'class': 'pretty'})
247
 
u'<input type="checkbox" name="is_cool" class="pretty" />'
248
 
 
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" />'
253
 
 
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" />'
258
 
 
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 &amp; goodbye" />'
270
 
 
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" />'
281
 
 
282
 
# Select Widget ###############################################################
283
 
 
284
 
>>> w = Select()
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>
291
 
</select>
292
 
 
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>
300
 
</select>
301
 
 
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>
309
 
</select>
310
 
 
311
 
The value is compared to its str():
312
 
>>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')])
313
 
<select name="num">
314
 
<option value="1">1</option>
315
 
<option value="2" selected="selected">2</option>
316
 
<option value="3">3</option>
317
 
</select>
318
 
>>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)])
319
 
<select name="num">
320
 
<option value="1">1</option>
321
 
<option value="2" selected="selected">2</option>
322
 
<option value="3">3</option>
323
 
</select>
324
 
>>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)])
325
 
<select name="num">
326
 
<option value="1">1</option>
327
 
<option value="2" selected="selected">2</option>
328
 
<option value="3">3</option>
329
 
</select>
330
 
 
331
 
The 'choices' argument can be any iterable:
332
 
>>> from itertools import chain
333
 
>>> def get_choices():
334
 
...     for i in range(5):
335
 
...         yield (i, i)
336
 
>>> print w.render('num', 2, choices=get_choices())
337
 
<select name="num">
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>
343
 
</select>
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]))
347
 
>>> f = SomeForm()
348
 
>>> f.as_table()
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>'
350
 
>>> f.as_table()
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})
353
 
>>> f.as_table()
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>'
355
 
 
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)
359
 
<select name="num">
360
 
<option value="1">1</option>
361
 
<option value="2" selected="selected">2</option>
362
 
<option value="3">3</option>
363
 
</select>
364
 
 
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)])
367
 
<select name="num">
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>
373
 
</select>
374
 
 
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>'
377
 
 
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)
382
 
<select name="num">
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>
388
 
</select>
389
 
>>> print w.render('num', 3)
390
 
<select name="num">
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>
396
 
</select>
397
 
 
398
 
# NullBooleanSelect Widget ####################################################
399
 
 
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>
406
 
</select>
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>
412
 
</select>
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>
418
 
</select>
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>
424
 
</select>
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>
430
 
</select>
431
 
 
432
 
# SelectMultiple Widget #######################################################
433
 
 
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>
441
 
</select>
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>
448
 
</select>
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>
455
 
</select>
456
 
 
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>
464
 
</select>
465
 
 
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>
473
 
</select>
474
 
 
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>
482
 
</select>
483
 
 
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>
490
 
</select>
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>
496
 
</select>
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>
502
 
</select>
503
 
 
504
 
The 'choices' argument can be any iterable:
505
 
>>> def get_choices():
506
 
...     for i in range(5):
507
 
...         yield (i, i)
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>
515
 
</select>
516
 
 
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>
524
 
</select>
525
 
 
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>
534
 
</select>
535
 
 
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>'
538
 
 
539
 
# RadioSelect Widget ##########################################################
540
 
 
541
 
>>> w = RadioSelect()
542
 
>>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
543
 
<ul>
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>
548
 
</ul>
549
 
 
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')))
552
 
<ul>
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>
557
 
</ul>
558
 
 
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')))
561
 
<ul>
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>
566
 
</ul>
567
 
 
568
 
The value is compared to its str():
569
 
>>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')])
570
 
<ul>
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>
574
 
</ul>
575
 
>>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)])
576
 
<ul>
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>
580
 
</ul>
581
 
>>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)])
582
 
<ul>
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>
586
 
</ul>
587
 
 
588
 
The 'choices' argument can be any iterable:
589
 
>>> def get_choices():
590
 
...     for i in range(5):
591
 
...         yield (i, i)
592
 
>>> print w.render('num', 2, choices=get_choices())
593
 
<ul>
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>
599
 
</ul>
600
 
 
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)
604
 
<ul>
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>
608
 
</ul>
609
 
 
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)])
612
 
<ul>
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>
618
 
</ul>
619
 
 
620
 
RadioSelect uses a RadioFieldRenderer to render the individual radio inputs.
621
 
You can manipulate that object directly to customize the way the RadioSelect
622
 
is rendered.
623
 
>>> w = RadioSelect()
624
 
>>> r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
625
 
>>> for inp in r:
626
 
...     print inp
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>
631
 
>>> for inp in r:
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 />
637
 
>>> for inp in r:
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>
643
 
>>> for inp in r:
644
 
...     print '%s %s %s %s %s' % (inp.name, inp.value, inp.choice_value, inp.choice_label, inp.is_checked())
645
 
beatle J J John True
646
 
beatle J P Paul False
647
 
beatle J G George False
648
 
beatle J R Ringo False
649
 
 
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>
660
 
 
661
 
A RadioFieldRenderer object also allows index access to individual RadioInput
662
 
objects.
663
 
>>> w = RadioSelect()
664
 
>>> r = w.get_renderer('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
665
 
>>> print r[1]
666
 
<label><input type="radio" name="beatle" value="P" /> Paul</label>
667
 
>>> print r[0]
668
 
<label><input checked="checked" type="radio" name="beatle" value="J" /> John</label>
669
 
>>> r[0].is_checked()
670
 
True
671
 
>>> r[1].is_checked()
672
 
False
673
 
>>> r[1].name, r[1].value, r[1].choice_value, r[1].choice_label
674
 
('beatle', u'J', u'P', u'Paul')
675
 
>>> r[10]
676
 
Traceback (most recent call last):
677
 
...
678
 
IndexError: list index out of range
679
 
 
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>'
684
 
 
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')))
688
 
<ul>
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>
693
 
</ul>
694
 
 
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'})
698
 
<ul>
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>
703
 
</ul>
704
 
 
705
 
# CheckboxSelectMultiple Widget ###############################################
706
 
 
707
 
>>> w = CheckboxSelectMultiple()
708
 
>>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
709
 
<ul>
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>
714
 
</ul>
715
 
>>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
716
 
<ul>
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>
721
 
</ul>
722
 
>>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo')))
723
 
<ul>
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>
728
 
</ul>
729
 
 
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')))
732
 
<ul>
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>
737
 
</ul>
738
 
 
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')))
741
 
<ul>
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>
746
 
</ul>
747
 
 
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')))
750
 
<ul>
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>
755
 
</ul>
756
 
 
757
 
The value is compared to its str():
758
 
>>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')])
759
 
<ul>
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>
763
 
</ul>
764
 
>>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)])
765
 
<ul>
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>
769
 
</ul>
770
 
>>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)])
771
 
<ul>
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>
775
 
</ul>
776
 
 
777
 
The 'choices' argument can be any iterable:
778
 
>>> def get_choices():
779
 
...     for i in range(5):
780
 
...         yield (i, i)
781
 
>>> print w.render('nums', [2], choices=get_choices())
782
 
<ul>
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>
788
 
</ul>
789
 
 
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])
793
 
<ul>
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>
797
 
</ul>
798
 
 
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)])
801
 
<ul>
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>
807
 
</ul>
808
 
 
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>'
811
 
 
812
 
# MultiWidget #################################################################
813
 
 
814
 
>>> class MyMultiWidget(MultiWidget):
815
 
...     def decompress(self, value):
816
 
...         if value:
817
 
...             return value.split('__')
818
 
...         return ['', '']
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" />'
831
 
 
832
 
# SplitDateTimeWidget #########################################################
833
 
 
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" />'
843
 
 
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" />'
849
 
 
850
 
##########
851
 
# Fields #
852
 
##########
853
 
 
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.
857
 
 
858
 
Each Field's __init__() takes at least these parameters:
859
 
    required -- Boolean that specifies whether the field is required.
860
 
                True by default.
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.
870
 
 
871
 
Other than that, the Field subclasses have class-specific options for
872
 
__init__(). For example, CharField has a max_length option.
873
 
 
874
 
# CharField ###################################################################
875
 
 
876
 
>>> f = CharField()
877
 
>>> f.clean(1)
878
 
u'1'
879
 
>>> f.clean('hello')
880
 
u'hello'
881
 
>>> f.clean(None)
882
 
Traceback (most recent call last):
883
 
...
884
 
ValidationError: [u'This field is required.']
885
 
>>> f.clean('')
886
 
Traceback (most recent call last):
887
 
...
888
 
ValidationError: [u'This field is required.']
889
 
>>> f.clean([1, 2, 3])
890
 
u'[1, 2, 3]'
891
 
 
892
 
>>> f = CharField(required=False)
893
 
>>> f.clean(1)
894
 
u'1'
895
 
>>> f.clean('hello')
896
 
u'hello'
897
 
>>> f.clean(None)
898
 
u''
899
 
>>> f.clean('')
900
 
u''
901
 
>>> f.clean([1, 2, 3])
902
 
u'[1, 2, 3]'
903
 
 
904
 
CharField accepts an optional max_length parameter:
905
 
>>> f = CharField(max_length=10, required=False)
906
 
>>> f.clean('12345')
907
 
u'12345'
908
 
>>> f.clean('1234567890')
909
 
u'1234567890'
910
 
>>> f.clean('1234567890a')
911
 
Traceback (most recent call last):
912
 
...
913
 
ValidationError: [u'Ensure this value has at most 10 characters (it has 11).']
914
 
 
915
 
CharField accepts an optional min_length parameter:
916
 
>>> f = CharField(min_length=10, required=False)
917
 
>>> f.clean('')
918
 
u''
919
 
>>> f.clean('12345')
920
 
Traceback (most recent call last):
921
 
...
922
 
ValidationError: [u'Ensure this value has at least 10 characters (it has 5).']
923
 
>>> f.clean('1234567890')
924
 
u'1234567890'
925
 
>>> f.clean('1234567890a')
926
 
u'1234567890a'
927
 
 
928
 
>>> f = CharField(min_length=10, required=True)
929
 
>>> f.clean('')
930
 
Traceback (most recent call last):
931
 
...
932
 
ValidationError: [u'This field is required.']
933
 
>>> f.clean('12345')
934
 
Traceback (most recent call last):
935
 
...
936
 
ValidationError: [u'Ensure this value has at least 10 characters (it has 5).']
937
 
>>> f.clean('1234567890')
938
 
u'1234567890'
939
 
>>> f.clean('1234567890a')
940
 
u'1234567890a'
941
 
 
942
 
# IntegerField ################################################################
943
 
 
944
 
>>> f = IntegerField()
945
 
>>> f.clean('')
946
 
Traceback (most recent call last):
947
 
...
948
 
ValidationError: [u'This field is required.']
949
 
>>> f.clean(None)
950
 
Traceback (most recent call last):
951
 
...
952
 
ValidationError: [u'This field is required.']
953
 
>>> f.clean('1')
954
 
1
955
 
>>> isinstance(f.clean('1'), int)
956
 
True
957
 
>>> f.clean('23')
958
 
23
959
 
>>> f.clean('a')
960
 
Traceback (most recent call last):
961
 
...
962
 
ValidationError: [u'Enter a whole number.']
963
 
>>> f.clean('1 ')
964
 
1
965
 
>>> f.clean(' 1')
966
 
1
967
 
>>> f.clean(' 1 ')
968
 
1
969
 
>>> f.clean('1a')
970
 
Traceback (most recent call last):
971
 
...
972
 
ValidationError: [u'Enter a whole number.']
973
 
 
974
 
>>> f = IntegerField(required=False)
975
 
>>> f.clean('')
976
 
>>> repr(f.clean(''))
977
 
'None'
978
 
>>> f.clean(None)
979
 
>>> repr(f.clean(None))
980
 
'None'
981
 
>>> f.clean('1')
982
 
1
983
 
>>> isinstance(f.clean('1'), int)
984
 
True
985
 
>>> f.clean('23')
986
 
23
987
 
>>> f.clean('a')
988
 
Traceback (most recent call last):
989
 
...
990
 
ValidationError: [u'Enter a whole number.']
991
 
>>> f.clean('1 ')
992
 
1
993
 
>>> f.clean(' 1')
994
 
1
995
 
>>> f.clean(' 1 ')
996
 
1
997
 
>>> f.clean('1a')
998
 
Traceback (most recent call last):
999
 
...
1000
 
ValidationError: [u'Enter a whole number.']
1001
 
 
1002
 
IntegerField accepts an optional max_value parameter:
1003
 
>>> f = IntegerField(max_value=10)
1004
 
>>> f.clean(None)
1005
 
Traceback (most recent call last):
1006
 
...
1007
 
ValidationError: [u'This field is required.']
1008
 
>>> f.clean(1)
1009
 
1
1010
 
>>> f.clean(10)
1011
 
10
1012
 
>>> f.clean(11)
1013
 
Traceback (most recent call last):
1014
 
...
1015
 
ValidationError: [u'Ensure this value is less than or equal to 10.']
1016
 
>>> f.clean('10')
1017
 
10
1018
 
>>> f.clean('11')
1019
 
Traceback (most recent call last):
1020
 
...
1021
 
ValidationError: [u'Ensure this value is less than or equal to 10.']
1022
 
 
1023
 
IntegerField accepts an optional min_value parameter:
1024
 
>>> f = IntegerField(min_value=10)
1025
 
>>> f.clean(None)
1026
 
Traceback (most recent call last):
1027
 
...
1028
 
ValidationError: [u'This field is required.']
1029
 
>>> f.clean(1)
1030
 
Traceback (most recent call last):
1031
 
...
1032
 
ValidationError: [u'Ensure this value is greater than or equal to 10.']
1033
 
>>> f.clean(10)
1034
 
10
1035
 
>>> f.clean(11)
1036
 
11
1037
 
>>> f.clean('10')
1038
 
10
1039
 
>>> f.clean('11')
1040
 
11
1041
 
 
1042
 
min_value and max_value can be used together:
1043
 
>>> f = IntegerField(min_value=10, max_value=20)
1044
 
>>> f.clean(None)
1045
 
Traceback (most recent call last):
1046
 
...
1047
 
ValidationError: [u'This field is required.']
1048
 
>>> f.clean(1)
1049
 
Traceback (most recent call last):
1050
 
...
1051
 
ValidationError: [u'Ensure this value is greater than or equal to 10.']
1052
 
>>> f.clean(10)
1053
 
10
1054
 
>>> f.clean(11)
1055
 
11
1056
 
>>> f.clean('10')
1057
 
10
1058
 
>>> f.clean('11')
1059
 
11
1060
 
>>> f.clean(20)
1061
 
20
1062
 
>>> f.clean(21)
1063
 
Traceback (most recent call last):
1064
 
...
1065
 
ValidationError: [u'Ensure this value is less than or equal to 20.']
1066
 
 
1067
 
# FloatField ##################################################################
1068
 
 
1069
 
>>> f = FloatField()
1070
 
>>> f.clean('')
1071
 
Traceback (most recent call last):
1072
 
...
1073
 
ValidationError: [u'This field is required.']
1074
 
>>> f.clean(None)
1075
 
Traceback (most recent call last):
1076
 
...
1077
 
ValidationError: [u'This field is required.']
1078
 
>>> f.clean('1')
1079
 
1.0
1080
 
>>> isinstance(f.clean('1'), float)
1081
 
True
1082
 
>>> f.clean('23')
1083
 
23.0
1084
 
>>> f.clean('3.14')
1085
 
3.1400000000000001
1086
 
>>> f.clean('a')
1087
 
Traceback (most recent call last):
1088
 
...
1089
 
ValidationError: [u'Enter a number.']
1090
 
>>> f.clean('1.0 ')
1091
 
1.0
1092
 
>>> f.clean(' 1.0')
1093
 
1.0
1094
 
>>> f.clean(' 1.0 ')
1095
 
1.0
1096
 
>>> f.clean('1.0a')
1097
 
Traceback (most recent call last):
1098
 
...
1099
 
ValidationError: [u'Enter a number.']
1100
 
 
1101
 
>>> f = FloatField(required=False)
1102
 
>>> f.clean('')
1103
 
 
1104
 
>>> f.clean(None)
1105
 
 
1106
 
>>> f.clean('1')
1107
 
1.0
1108
 
 
1109
 
FloatField accepts min_value and max_value just like IntegerField:
1110
 
>>> f = FloatField(max_value=1.5, min_value=0.5)
1111
 
 
1112
 
>>> f.clean('1.6')
1113
 
Traceback (most recent call last):
1114
 
...
1115
 
ValidationError: [u'Ensure this value is less than or equal to 1.5.']
1116
 
>>> f.clean('0.4')
1117
 
Traceback (most recent call last):
1118
 
...
1119
 
ValidationError: [u'Ensure this value is greater than or equal to 0.5.']
1120
 
>>> f.clean('1.5')
1121
 
1.5
1122
 
>>> f.clean('0.5')
1123
 
0.5
1124
 
 
1125
 
# DecimalField ################################################################
1126
 
 
1127
 
>>> f = DecimalField(max_digits=4, decimal_places=2)
1128
 
>>> f.clean('')
1129
 
Traceback (most recent call last):
1130
 
...
1131
 
ValidationError: [u'This field is required.']
1132
 
>>> f.clean(None)
1133
 
Traceback (most recent call last):
1134
 
...
1135
 
ValidationError: [u'This field is required.']
1136
 
>>> f.clean('1')
1137
 
Decimal("1")
1138
 
>>> isinstance(f.clean('1'), Decimal)
1139
 
True
1140
 
>>> f.clean('23')
1141
 
Decimal("23")
1142
 
>>> f.clean('3.14')
1143
 
Decimal("3.14")
1144
 
>>> f.clean('a')
1145
 
Traceback (most recent call last):
1146
 
...
1147
 
ValidationError: [u'Enter a number.']
1148
 
>>> f.clean('1.0 ')
1149
 
Decimal("1.0")
1150
 
>>> f.clean(' 1.0')
1151
 
Decimal("1.0")
1152
 
>>> f.clean(' 1.0 ')
1153
 
Decimal("1.0")
1154
 
>>> f.clean('1.0a')
1155
 
Traceback (most recent call last):
1156
 
...
1157
 
ValidationError: [u'Enter a number.']
1158
 
>>> f.clean('123.45')
1159
 
Traceback (most recent call last):
1160
 
...
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):
1164
 
...
1165
 
ValidationError: [u'Ensure that there are no more than 2 decimal places.']
1166
 
>>> f.clean('123.4')
1167
 
Traceback (most recent call last):
1168
 
...
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)
1171
 
>>> f.clean('')
1172
 
 
1173
 
>>> f.clean(None)
1174
 
 
1175
 
>>> f.clean('1')
1176
 
Decimal("1")
1177
 
 
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'))
1180
 
 
1181
 
>>> f.clean('1.6')
1182
 
Traceback (most recent call last):
1183
 
...
1184
 
ValidationError: [u'Ensure this value is less than or equal to 1.5.']
1185
 
>>> f.clean('0.4')
1186
 
Traceback (most recent call last):
1187
 
...
1188
 
ValidationError: [u'Ensure this value is greater than or equal to 0.5.']
1189
 
>>> f.clean('1.5')
1190
 
Decimal("1.5")
1191
 
>>> f.clean('0.5')
1192
 
Decimal("0.5")
1193
 
>>> f.clean('.5')
1194
 
Decimal("0.5")
1195
 
>>> f.clean('00.50')
1196
 
Decimal("0.50")
1197
 
 
1198
 
# DateField ###################################################################
1199
 
 
1200
 
>>> import datetime
1201
 
>>> f = 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):
1228
 
...
1229
 
ValidationError: [u'Enter a valid date.']
1230
 
>>> f.clean('200a-10-25')
1231
 
Traceback (most recent call last):
1232
 
...
1233
 
ValidationError: [u'Enter a valid date.']
1234
 
>>> f.clean('25/10/06')
1235
 
Traceback (most recent call last):
1236
 
...
1237
 
ValidationError: [u'Enter a valid date.']
1238
 
>>> f.clean(None)
1239
 
Traceback (most recent call last):
1240
 
...
1241
 
ValidationError: [u'This field is required.']
1242
 
 
1243
 
>>> f = DateField(required=False)
1244
 
>>> f.clean(None)
1245
 
>>> repr(f.clean(None))
1246
 
'None'
1247
 
>>> f.clean('')
1248
 
>>> repr(f.clean(''))
1249
 
'None'
1250
 
 
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)
1259
 
 
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):
1264
 
...
1265
 
ValidationError: [u'Enter a valid date.']
1266
 
>>> f.clean('10/25/2006')
1267
 
Traceback (most recent call last):
1268
 
...
1269
 
ValidationError: [u'Enter a valid date.']
1270
 
>>> f.clean('10/25/06')
1271
 
Traceback (most recent call last):
1272
 
...
1273
 
ValidationError: [u'Enter a valid date.']
1274
 
 
1275
 
# TimeField ###################################################################
1276
 
 
1277
 
>>> import datetime
1278
 
>>> f = 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):
1289
 
...
1290
 
ValidationError: [u'Enter a valid time.']
1291
 
>>> f.clean('1:24 p.m.')
1292
 
Traceback (most recent call last):
1293
 
...
1294
 
ValidationError: [u'Enter a valid time.']
1295
 
 
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)
1306
 
 
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):
1311
 
...
1312
 
ValidationError: [u'Enter a valid time.']
1313
 
 
1314
 
# DateTimeField ###############################################################
1315
 
 
1316
 
>>> import datetime
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):
1352
 
...
1353
 
ValidationError: [u'Enter a valid date/time.']
1354
 
>>> f.clean('2006-10-25 4:30 p.m.')
1355
 
Traceback (most recent call last):
1356
 
...
1357
 
ValidationError: [u'Enter a valid date/time.']
1358
 
 
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)
1371
 
 
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):
1376
 
...
1377
 
ValidationError: [u'Enter a valid date/time.']
1378
 
 
1379
 
>>> f = DateTimeField(required=False)
1380
 
>>> f.clean(None)
1381
 
>>> repr(f.clean(None))
1382
 
'None'
1383
 
>>> f.clean('')
1384
 
>>> repr(f.clean(''))
1385
 
'None'
1386
 
 
1387
 
# RegexField ##################################################################
1388
 
 
1389
 
>>> f = RegexField('^\d[A-F]\d$')
1390
 
>>> f.clean('2A2')
1391
 
u'2A2'
1392
 
>>> f.clean('3F3')
1393
 
u'3F3'
1394
 
>>> f.clean('3G3')
1395
 
Traceback (most recent call last):
1396
 
...
1397
 
ValidationError: [u'Enter a valid value.']
1398
 
>>> f.clean(' 2A2')
1399
 
Traceback (most recent call last):
1400
 
...
1401
 
ValidationError: [u'Enter a valid value.']
1402
 
>>> f.clean('2A2 ')
1403
 
Traceback (most recent call last):
1404
 
...
1405
 
ValidationError: [u'Enter a valid value.']
1406
 
>>> f.clean('')
1407
 
Traceback (most recent call last):
1408
 
...
1409
 
ValidationError: [u'This field is required.']
1410
 
 
1411
 
>>> f = RegexField('^\d[A-F]\d$', required=False)
1412
 
>>> f.clean('2A2')
1413
 
u'2A2'
1414
 
>>> f.clean('3F3')
1415
 
u'3F3'
1416
 
>>> f.clean('3G3')
1417
 
Traceback (most recent call last):
1418
 
...
1419
 
ValidationError: [u'Enter a valid value.']
1420
 
>>> f.clean('')
1421
 
u''
1422
 
 
1423
 
Alternatively, RegexField can take a compiled regular expression:
1424
 
>>> f = RegexField(re.compile('^\d[A-F]\d$'))
1425
 
>>> f.clean('2A2')
1426
 
u'2A2'
1427
 
>>> f.clean('3F3')
1428
 
u'3F3'
1429
 
>>> f.clean('3G3')
1430
 
Traceback (most recent call last):
1431
 
...
1432
 
ValidationError: [u'Enter a valid value.']
1433
 
>>> f.clean(' 2A2')
1434
 
Traceback (most recent call last):
1435
 
...
1436
 
ValidationError: [u'Enter a valid value.']
1437
 
>>> f.clean('2A2 ')
1438
 
Traceback (most recent call last):
1439
 
...
1440
 
ValidationError: [u'Enter a valid value.']
1441
 
 
1442
 
RegexField takes an optional error_message argument:
1443
 
>>> f = RegexField('^\d\d\d\d$', error_message='Enter a four-digit number.')
1444
 
>>> f.clean('1234')
1445
 
u'1234'
1446
 
>>> f.clean('123')
1447
 
Traceback (most recent call last):
1448
 
...
1449
 
ValidationError: [u'Enter a four-digit number.']
1450
 
>>> f.clean('abcd')
1451
 
Traceback (most recent call last):
1452
 
...
1453
 
ValidationError: [u'Enter a four-digit number.']
1454
 
 
1455
 
RegexField also access min_length and max_length parameters, for convenience.
1456
 
>>> f = RegexField('^\d+$', min_length=5, max_length=10)
1457
 
>>> f.clean('123')
1458
 
Traceback (most recent call last):
1459
 
...
1460
 
ValidationError: [u'Ensure this value has at least 5 characters (it has 3).']
1461
 
>>> f.clean('abc')
1462
 
Traceback (most recent call last):
1463
 
...
1464
 
ValidationError: [u'Ensure this value has at least 5 characters (it has 3).']
1465
 
>>> f.clean('12345')
1466
 
u'12345'
1467
 
>>> f.clean('1234567890')
1468
 
u'1234567890'
1469
 
>>> f.clean('12345678901')
1470
 
Traceback (most recent call last):
1471
 
...
1472
 
ValidationError: [u'Ensure this value has at most 10 characters (it has 11).']
1473
 
>>> f.clean('12345a')
1474
 
Traceback (most recent call last):
1475
 
...
1476
 
ValidationError: [u'Enter a valid value.']
1477
 
 
1478
 
# EmailField ##################################################################
1479
 
 
1480
 
>>> f = EmailField()
1481
 
>>> f.clean('')
1482
 
Traceback (most recent call last):
1483
 
...
1484
 
ValidationError: [u'This field is required.']
1485
 
>>> f.clean(None)
1486
 
Traceback (most recent call last):
1487
 
...
1488
 
ValidationError: [u'This field is required.']
1489
 
>>> f.clean('person@example.com')
1490
 
u'person@example.com'
1491
 
>>> f.clean('foo')
1492
 
Traceback (most recent call last):
1493
 
...
1494
 
ValidationError: [u'Enter a valid e-mail address.']
1495
 
>>> f.clean('foo@')
1496
 
Traceback (most recent call last):
1497
 
...
1498
 
ValidationError: [u'Enter a valid e-mail address.']
1499
 
>>> f.clean('foo@bar')
1500
 
Traceback (most recent call last):
1501
 
...
1502
 
ValidationError: [u'Enter a valid e-mail address.']
1503
 
 
1504
 
>>> f = EmailField(required=False)
1505
 
>>> f.clean('')
1506
 
u''
1507
 
>>> f.clean(None)
1508
 
u''
1509
 
>>> f.clean('person@example.com')
1510
 
u'person@example.com'
1511
 
>>> f.clean('foo')
1512
 
Traceback (most recent call last):
1513
 
...
1514
 
ValidationError: [u'Enter a valid e-mail address.']
1515
 
>>> f.clean('foo@')
1516
 
Traceback (most recent call last):
1517
 
...
1518
 
ValidationError: [u'Enter a valid e-mail address.']
1519
 
>>> f.clean('foo@bar')
1520
 
Traceback (most recent call last):
1521
 
...
1522
 
ValidationError: [u'Enter a valid e-mail address.']
1523
 
 
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):
1528
 
...
1529
 
ValidationError: [u'Ensure this value has at least 10 characters (it has 9).']
1530
 
>>> f.clean('alf@foo.com')
1531
 
u'alf@foo.com'
1532
 
>>> f.clean('alf123456788@foo.com')
1533
 
Traceback (most recent call last):
1534
 
...
1535
 
ValidationError: [u'Ensure this value has at most 15 characters (it has 20).']
1536
 
 
1537
 
# FileField ##################################################################
1538
 
 
1539
 
>>> f = FileField()
1540
 
>>> f.clean('')
1541
 
Traceback (most recent call last):
1542
 
...
1543
 
ValidationError: [u'This field is required.']
1544
 
 
1545
 
>>> f.clean(None)
1546
 
Traceback (most recent call last):
1547
 
...
1548
 
ValidationError: [u'This field is required.']
1549
 
 
1550
 
>>> f.clean({})
1551
 
Traceback (most recent call last):
1552
 
...
1553
 
ValidationError: [u'No file was submitted.']
1554
 
 
1555
 
>>> f.clean('some content that is not a file')
1556
 
Traceback (most recent call last):
1557
 
...
1558
 
ValidationError: [u'No file was submitted. Check the encoding type on the form.']
1559
 
 
1560
 
>>> f.clean({'filename': 'name', 'content':None})
1561
 
Traceback (most recent call last):
1562
 
...
1563
 
ValidationError: [u'The submitted file is empty.']
1564
 
 
1565
 
>>> f.clean({'filename': 'name', 'content':''})
1566
 
Traceback (most recent call last):
1567
 
...
1568
 
ValidationError: [u'The submitted file is empty.']
1569
 
 
1570
 
>>> type(f.clean({'filename': 'name', 'content':'Some File Content'}))
1571
 
<class 'django.newforms.fields.UploadedFile'>
1572
 
 
1573
 
# URLField ##################################################################
1574
 
 
1575
 
>>> f = URLField()
1576
 
>>> f.clean('')
1577
 
Traceback (most recent call last):
1578
 
...
1579
 
ValidationError: [u'This field is required.']
1580
 
>>> f.clean(None)
1581
 
Traceback (most recent call last):
1582
 
...
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'
1588
 
>>> f.clean('foo')
1589
 
Traceback (most recent call last):
1590
 
...
1591
 
ValidationError: [u'Enter a valid URL.']
1592
 
>>> f.clean('example.com')
1593
 
Traceback (most recent call last):
1594
 
...
1595
 
ValidationError: [u'Enter a valid URL.']
1596
 
>>> f.clean('http://')
1597
 
Traceback (most recent call last):
1598
 
...
1599
 
ValidationError: [u'Enter a valid URL.']
1600
 
>>> f.clean('http://example')
1601
 
Traceback (most recent call last):
1602
 
...
1603
 
ValidationError: [u'Enter a valid URL.']
1604
 
>>> f.clean('http://example.')
1605
 
Traceback (most recent call last):
1606
 
...
1607
 
ValidationError: [u'Enter a valid URL.']
1608
 
>>> f.clean('http://.com')
1609
 
Traceback (most recent call last):
1610
 
...
1611
 
ValidationError: [u'Enter a valid URL.']
1612
 
 
1613
 
>>> f = URLField(required=False)
1614
 
>>> f.clean('')
1615
 
u''
1616
 
>>> f.clean(None)
1617
 
u''
1618
 
>>> f.clean('http://example.com')
1619
 
u'http://example.com'
1620
 
>>> f.clean('http://www.example.com')
1621
 
u'http://www.example.com'
1622
 
>>> f.clean('foo')
1623
 
Traceback (most recent call last):
1624
 
...
1625
 
ValidationError: [u'Enter a valid URL.']
1626
 
>>> f.clean('example.com')
1627
 
Traceback (most recent call last):
1628
 
...
1629
 
ValidationError: [u'Enter a valid URL.']
1630
 
>>> f.clean('http://')
1631
 
Traceback (most recent call last):
1632
 
...
1633
 
ValidationError: [u'Enter a valid URL.']
1634
 
>>> f.clean('http://example')
1635
 
Traceback (most recent call last):
1636
 
...
1637
 
ValidationError: [u'Enter a valid URL.']
1638
 
>>> f.clean('http://example.')
1639
 
Traceback (most recent call last):
1640
 
...
1641
 
ValidationError: [u'Enter a valid URL.']
1642
 
>>> f.clean('http://.com')
1643
 
Traceback (most recent call last):
1644
 
...
1645
 
ValidationError: [u'Enter a valid URL.']
1646
 
 
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):
1654
 
...
1655
 
ValidationError: [u'Enter a valid URL.']
1656
 
>>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com') # bad domain
1657
 
Traceback (most recent call last):
1658
 
...
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):
1662
 
...
1663
 
ValidationError: [u'This URL appears to be a broken link.']
1664
 
>>> f = URLField(verify_exists=True, required=False)
1665
 
>>> f.clean('')
1666
 
u''
1667
 
>>> f.clean('http://www.google.com') # This will fail if there's no Internet connection
1668
 
u'http://www.google.com'
1669
 
 
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):
1674
 
...
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):
1680
 
...
1681
 
ValidationError: [u'Ensure this value has at most 20 characters (it has 37).']
1682
 
 
1683
 
# BooleanField ################################################################
1684
 
 
1685
 
>>> f = BooleanField()
1686
 
>>> f.clean('')
1687
 
Traceback (most recent call last):
1688
 
...
1689
 
ValidationError: [u'This field is required.']
1690
 
>>> f.clean(None)
1691
 
Traceback (most recent call last):
1692
 
...
1693
 
ValidationError: [u'This field is required.']
1694
 
>>> f.clean(True)
1695
 
True
1696
 
>>> f.clean(False)
1697
 
False
1698
 
>>> f.clean(1)
1699
 
True
1700
 
>>> f.clean(0)
1701
 
False
1702
 
>>> f.clean('Django rocks')
1703
 
True
1704
 
 
1705
 
>>> f = BooleanField(required=False)
1706
 
>>> f.clean('')
1707
 
False
1708
 
>>> f.clean(None)
1709
 
False
1710
 
>>> f.clean(True)
1711
 
True
1712
 
>>> f.clean(False)
1713
 
False
1714
 
>>> f.clean(1)
1715
 
True
1716
 
>>> f.clean(0)
1717
 
False
1718
 
>>> f.clean('Django rocks')
1719
 
True
1720
 
 
1721
 
# ChoiceField #################################################################
1722
 
 
1723
 
>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')])
1724
 
>>> f.clean('')
1725
 
Traceback (most recent call last):
1726
 
...
1727
 
ValidationError: [u'This field is required.']
1728
 
>>> f.clean(None)
1729
 
Traceback (most recent call last):
1730
 
...
1731
 
ValidationError: [u'This field is required.']
1732
 
>>> f.clean(1)
1733
 
u'1'
1734
 
>>> f.clean('1')
1735
 
u'1'
1736
 
>>> f.clean('3')
1737
 
Traceback (most recent call last):
1738
 
...
1739
 
ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
1740
 
 
1741
 
>>> f = ChoiceField(choices=[('1', '1'), ('2', '2')], required=False)
1742
 
>>> f.clean('')
1743
 
u''
1744
 
>>> f.clean(None)
1745
 
u''
1746
 
>>> f.clean(1)
1747
 
u'1'
1748
 
>>> f.clean('1')
1749
 
u'1'
1750
 
>>> f.clean('3')
1751
 
Traceback (most recent call last):
1752
 
...
1753
 
ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
1754
 
 
1755
 
>>> f = ChoiceField(choices=[('J', 'John'), ('P', 'Paul')])
1756
 
>>> f.clean('J')
1757
 
u'J'
1758
 
>>> f.clean('John')
1759
 
Traceback (most recent call last):
1760
 
...
1761
 
ValidationError: [u'Select a valid choice. That choice is not one of the available choices.']
1762
 
 
1763
 
# NullBooleanField ############################################################
1764
 
 
1765
 
>>> f = NullBooleanField()
1766
 
>>> f.clean('')
1767
 
>>> f.clean(True)
1768
 
True
1769
 
>>> f.clean(False)
1770
 
False
1771
 
>>> f.clean(None)
1772
 
>>> f.clean('1')
1773
 
>>> f.clean('2')
1774
 
>>> f.clean('3')
1775
 
>>> f.clean('hello')
1776
 
 
1777
 
# MultipleChoiceField #########################################################
1778
 
 
1779
 
>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')])
1780
 
>>> f.clean('')
1781
 
Traceback (most recent call last):
1782
 
...
1783
 
ValidationError: [u'This field is required.']
1784
 
>>> f.clean(None)
1785
 
Traceback (most recent call last):
1786
 
...
1787
 
ValidationError: [u'This field is required.']
1788
 
>>> f.clean([1])
1789
 
[u'1']
1790
 
>>> f.clean(['1'])
1791
 
[u'1']
1792
 
>>> f.clean(['1', '2'])
1793
 
[u'1', u'2']
1794
 
>>> f.clean([1, '2'])
1795
 
[u'1', u'2']
1796
 
>>> f.clean((1, '2'))
1797
 
[u'1', u'2']
1798
 
>>> f.clean('hello')
1799
 
Traceback (most recent call last):
1800
 
...
1801
 
ValidationError: [u'Enter a list of values.']
1802
 
>>> f.clean([])
1803
 
Traceback (most recent call last):
1804
 
...
1805
 
ValidationError: [u'This field is required.']
1806
 
>>> f.clean(())
1807
 
Traceback (most recent call last):
1808
 
...
1809
 
ValidationError: [u'This field is required.']
1810
 
>>> f.clean(['3'])
1811
 
Traceback (most recent call last):
1812
 
...
1813
 
ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
1814
 
 
1815
 
>>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')], required=False)
1816
 
>>> f.clean('')
1817
 
[]
1818
 
>>> f.clean(None)
1819
 
[]
1820
 
>>> f.clean([1])
1821
 
[u'1']
1822
 
>>> f.clean(['1'])
1823
 
[u'1']
1824
 
>>> f.clean(['1', '2'])
1825
 
[u'1', u'2']
1826
 
>>> f.clean([1, '2'])
1827
 
[u'1', u'2']
1828
 
>>> f.clean((1, '2'))
1829
 
[u'1', u'2']
1830
 
>>> f.clean('hello')
1831
 
Traceback (most recent call last):
1832
 
...
1833
 
ValidationError: [u'Enter a list of values.']
1834
 
>>> f.clean([])
1835
 
[]
1836
 
>>> f.clean(())
1837
 
[]
1838
 
>>> f.clean(['3'])
1839
 
Traceback (most recent call last):
1840
 
...
1841
 
ValidationError: [u'Select a valid choice. 3 is not one of the available choices.']
1842
 
 
1843
 
# ComboField ##################################################################
1844
 
 
1845
 
ComboField takes a list of fields that should be used to validate a value,
1846
 
in that order.
1847
 
>>> f = ComboField(fields=[CharField(max_length=20), EmailField()])
1848
 
>>> f.clean('test@example.com')
1849
 
u'test@example.com'
1850
 
>>> f.clean('longemailaddress@example.com')
1851
 
Traceback (most recent call last):
1852
 
...
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):
1856
 
...
1857
 
ValidationError: [u'Enter a valid e-mail address.']
1858
 
>>> f.clean('')
1859
 
Traceback (most recent call last):
1860
 
...
1861
 
ValidationError: [u'This field is required.']
1862
 
>>> f.clean(None)
1863
 
Traceback (most recent call last):
1864
 
...
1865
 
ValidationError: [u'This field is required.']
1866
 
 
1867
 
>>> f = ComboField(fields=[CharField(max_length=20), EmailField()], required=False)
1868
 
>>> f.clean('test@example.com')
1869
 
u'test@example.com'
1870
 
>>> f.clean('longemailaddress@example.com')
1871
 
Traceback (most recent call last):
1872
 
...
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):
1876
 
...
1877
 
ValidationError: [u'Enter a valid e-mail address.']
1878
 
>>> f.clean('')
1879
 
u''
1880
 
>>> f.clean(None)
1881
 
u''
1882
 
 
1883
 
# SplitDateTimeField ##########################################################
1884
 
 
1885
 
>>> f = SplitDateTimeField()
1886
 
>>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)])
1887
 
datetime.datetime(2006, 1, 10, 7, 30)
1888
 
>>> f.clean(None)
1889
 
Traceback (most recent call last):
1890
 
...
1891
 
ValidationError: [u'This field is required.']
1892
 
>>> f.clean('')
1893
 
Traceback (most recent call last):
1894
 
...
1895
 
ValidationError: [u'This field is required.']
1896
 
>>> f.clean('hello')
1897
 
Traceback (most recent call last):
1898
 
...
1899
 
ValidationError: [u'Enter a list of values.']
1900
 
>>> f.clean(['hello', 'there'])
1901
 
Traceback (most recent call last):
1902
 
...
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):
1906
 
...
1907
 
ValidationError: [u'Enter a valid time.']
1908
 
>>> f.clean(['hello', '07:30'])
1909
 
Traceback (most recent call last):
1910
 
...
1911
 
ValidationError: [u'Enter a valid date.']
1912
 
 
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)
1918
 
>>> f.clean(None)
1919
 
>>> f.clean('')
1920
 
>>> f.clean([''])
1921
 
>>> f.clean(['', ''])
1922
 
>>> f.clean('hello')
1923
 
Traceback (most recent call last):
1924
 
...
1925
 
ValidationError: [u'Enter a list of values.']
1926
 
>>> f.clean(['hello', 'there'])
1927
 
Traceback (most recent call last):
1928
 
...
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):
1932
 
...
1933
 
ValidationError: [u'Enter a valid time.']
1934
 
>>> f.clean(['hello', '07:30'])
1935
 
Traceback (most recent call last):
1936
 
...
1937
 
ValidationError: [u'Enter a valid date.']
1938
 
>>> f.clean(['2006-01-10', ''])
1939
 
Traceback (most recent call last):
1940
 
...
1941
 
ValidationError: [u'Enter a valid time.']
1942
 
>>> f.clean(['2006-01-10'])
1943
 
Traceback (most recent call last):
1944
 
...
1945
 
ValidationError: [u'Enter a valid time.']
1946
 
>>> f.clean(['', '07:30'])
1947
 
Traceback (most recent call last):
1948
 
...
1949
 
ValidationError: [u'Enter a valid date.']
1950
 
 
1951
 
#########
1952
 
# Forms #
1953
 
#########
1954
 
 
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.
1958
 
 
1959
 
# Form ########################################################################
1960
 
 
1961
 
>>> class Person(Form):
1962
 
...     first_name = CharField()
1963
 
...     last_name = CharField()
1964
 
...     birthday = DateField()
1965
 
 
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'})
1968
 
>>> p.is_bound
1969
 
True
1970
 
>>> p.errors
1971
 
{}
1972
 
>>> p.is_valid()
1973
 
True
1974
 
>>> p.errors.as_ul()
1975
 
u''
1976
 
>>> p.errors.as_text()
1977
 
u''
1978
 
>>> p.cleaned_data
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):
1988
 
...
1989
 
KeyError: "Key 'nonexistentfield' not found in Form"
1990
 
 
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
1998
 
First name John
1999
 
Last name Lennon
2000
 
Birthday 1940-10-9
2001
 
>>> print p
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>
2005
 
 
2006
 
Empty dictionaries are valid, too.
2007
 
>>> p = Person({})
2008
 
>>> p.is_bound
2009
 
True
2010
 
>>> p.errors
2011
 
{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']}
2012
 
>>> p.is_valid()
2013
 
False
2014
 
>>> p.cleaned_data
2015
 
Traceback (most recent call last):
2016
 
...
2017
 
AttributeError: 'Person' object has no attribute 'cleaned_data'
2018
 
>>> print p
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>
2026
 
>>> print p.as_ul()
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>
2030
 
>>> print p.as_p()
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>
2037
 
 
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.
2041
 
>>> p = Person()
2042
 
>>> p.is_bound
2043
 
False
2044
 
>>> p.errors
2045
 
{}
2046
 
>>> p.is_valid()
2047
 
False
2048
 
>>> p.cleaned_data
2049
 
Traceback (most recent call last):
2050
 
...
2051
 
AttributeError: 'Person' object has no attribute 'cleaned_data'
2052
 
>>> print p
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>
2060
 
>>> print p.as_ul()
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>
2064
 
>>> print p.as_p()
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>
2068
 
 
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'})
2071
 
>>> p.as_table()
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>'
2073
 
>>> p.as_ul()
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>'
2075
 
>>> p.as_p()
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>'
2077
 
 
2078
 
>>> p = Person({'last_name': u'Lennon'})
2079
 
>>> p.errors
2080
 
{'first_name': [u'This field is required.'], 'birthday': [u'This field is required.']}
2081
 
>>> p.is_valid()
2082
 
False
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()
2086
 
* first_name
2087
 
  * This field is required.
2088
 
* birthday
2089
 
  * This field is required.
2090
 
>>> p.cleaned_data
2091
 
Traceback (most recent call last):
2092
 
...
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.'
2100
 
 
2101
 
>>> p = Person()
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" />
2108
 
 
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)
2115
 
>>> p.is_valid()
2116
 
True
2117
 
>>> p.cleaned_data
2118
 
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
2119
 
 
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
2124
 
empty string.
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)
2131
 
>>> f.is_valid()
2132
 
True
2133
 
>>> f.cleaned_data
2134
 
{'nick_name': u'', 'first_name': u'John', 'last_name': u'Lennon'}
2135
 
 
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)
2143
 
>>> f.is_valid()
2144
 
True
2145
 
>>> f.cleaned_data
2146
 
{'birth_date': None, 'first_name': u'John', 'last_name': u'Lennon'}
2147
 
 
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>
2157
 
>>> print p.as_ul()
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>
2161
 
>>> print p.as_p()
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>
2165
 
 
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)
2169
 
>>> print p.as_ul()
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>
2173
 
 
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)
2177
 
>>> print p.as_ul()
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>
2181
 
 
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)
2189
 
>>> print p.as_ul()
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>
2193
 
 
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)
2197
 
>>> print p.as_ul()
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>
2201
 
 
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" />
2210
 
 
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" />
2216
 
 
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>
2226
 
 
2227
 
as_textarea(), as_text() and as_hidden() are shortcuts for changing the output
2228
 
widget type:
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" />'
2235
 
 
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>
2243
 
 
2244
 
Instance-level attrs are *not* carried over to as_textarea(), as_text() and
2245
 
as_hidden():
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." />'
2255
 
 
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>
2265
 
</select>
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>
2271
 
</select>
2272
 
 
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>
2284
 
</select>
2285
 
 
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>
2295
 
</select>
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>
2301
 
</select>
2302
 
 
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>
2314
 
</select>
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>
2320
 
</select>
2321
 
 
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">
2329
 
</select>
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>
2335
 
</select>
2336
 
 
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']
2343
 
<ul>
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>
2346
 
</ul>
2347
 
>>> print f
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>
2352
 
</ul></td></tr>
2353
 
>>> print f.as_ul()
2354
 
<li>Name: <input type="text" name="name" /></li>
2355
 
<li>Language: <ul>
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>
2358
 
</ul></li>
2359
 
 
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
2362
 
zero-based index.
2363
 
>>> f = FrameworkForm(auto_id='id_%s')
2364
 
>>> print f['language']
2365
 
<ul>
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>
2368
 
</ul>
2369
 
 
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.
2373
 
>>> print f
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>
2378
 
</ul></td></tr>
2379
 
>>> print f.as_ul()
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>
2384
 
</ul></li>
2385
 
>>> print f.as_p()
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>
2390
 
</ul></p>
2391
 
 
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">
2399
 
</select>
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>
2408
 
</select>
2409
 
>>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False)
2410
 
>>> print f['name']
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>
2416
 
</select>
2417
 
 
2418
 
MultipleChoiceField rendered as_hidden() is a special case. Because it can
2419
 
have multiple values, its as_hidden() renders multiple <input type="hidden">
2420
 
tags.
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" />
2428
 
 
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']
2435
 
<ul>
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>
2438
 
</ul>
2439
 
>>> f = SongForm({'composers': ['J']}, auto_id=False)
2440
 
>>> print f['composers']
2441
 
<ul>
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>
2444
 
</ul>
2445
 
>>> f = SongForm({'composers': ['J', 'P']}, auto_id=False)
2446
 
>>> print f['composers']
2447
 
<ul>
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>
2450
 
</ul>
2451
 
 
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
2454
 
zero-based index.
2455
 
>>> f = SongForm(auto_id='%s_id')
2456
 
>>> print f['composers']
2457
 
<ul>
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>
2460
 
</ul>
2461
 
 
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)
2466
 
>>> f.errors
2467
 
{}
2468
 
>>> from django.http import QueryDict
2469
 
>>> data = QueryDict('name=Yesterday&composers=J&composers=P')
2470
 
>>> f = SongForm(data)
2471
 
>>> f.errors
2472
 
{}
2473
 
>>> from django.utils.datastructures import MultiValueDict
2474
 
>>> data = MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P']))
2475
 
>>> f = SongForm(data)
2476
 
>>> f.errors
2477
 
{}
2478
 
 
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)
2484
 
>>> print f.as_ul()
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>
2487
 
 
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)
2491
 
>>> f.errors
2492
 
{'composers': [u'This field is required.']}
2493
 
>>> f = SongForm({'name': 'Yesterday', 'composers': ['J']}, auto_id=False)
2494
 
>>> f.errors
2495
 
{}
2496
 
>>> f.cleaned_data
2497
 
{'composers': [u'J'], 'name': u'Yesterday'}
2498
 
>>> f = SongForm({'name': 'Yesterday', 'composers': ['J', 'P']}, auto_id=False)
2499
 
>>> f.errors
2500
 
{}
2501
 
>>> f.cleaned_data
2502
 
{'composers': [u'J', u'P'], 'name': u'Yesterday'}
2503
 
 
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'])
2509
 
 
2510
 
>>> f = EscapingForm({'special_name': "Nothing to escape"}, auto_id=False)
2511
 
>>> print f
2512
 
<tr><th>Special name:</th><td><ul class="errorlist"><li>Something&#39;s wrong with &#39;Nothing to escape&#39;</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)
2514
 
>>> print f
2515
 
<tr><th>Special name:</th><td><ul class="errorlist"><li>Something&#39;s wrong with &#39;Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;&#39;</li></ul><input type="text" name="special_name" value="Should escape &lt; &amp; &gt; and &lt;script&gt;alert(&#39;xss&#39;)&lt;/script&gt;" /></td></tr>
2516
 
 
2517
 
# Validating multiple fields in relation to another ###########################
2518
 
 
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)
2535
 
>>> f.errors
2536
 
{}
2537
 
>>> f = UserRegistration({}, auto_id=False)
2538
 
>>> f.errors
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)
2541
 
>>> f.errors
2542
 
{'password2': [u'Please make sure your passwords match.']}
2543
 
>>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False)
2544
 
>>> f.errors
2545
 
{}
2546
 
>>> f.cleaned_data
2547
 
{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'}
2548
 
 
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)
2565
 
>>> f.errors
2566
 
{}
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>
2572
 
>>> f.errors
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)
2575
 
>>> f.errors
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>
2582
 
>>> print f.as_ul()
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)
2588
 
>>> f.errors
2589
 
{}
2590
 
>>> f.cleaned_data
2591
 
{'username': u'adrian', 'password1': u'foo', 'password2': u'foo'}
2592
 
 
2593
 
# Dynamic construction ########################################################
2594
 
 
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)
2605
 
>>> print p
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>
2609
 
 
2610
 
Instances of a dynamic Form do not persist fields from one Form instance to
2611
 
the next.
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)
2619
 
>>> print my_form
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)
2624
 
>>> print my_form
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>
2627
 
 
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)
2637
 
>>> print my_form
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)
2644
 
>>> print my_form
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>
2649
 
 
2650
 
Similarly, changes to field attributes do not persist from one Form instance
2651
 
to the next.
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
2662
 
(False, False)
2663
 
>>> f = Person(names_required=True)
2664
 
>>> f['first_name'].field.required, f['last_name'].field.required
2665
 
(True, True)
2666
 
>>> f = Person(names_required=False)
2667
 
>>> f['first_name'].field.required, f['last_name'].field.required
2668
 
(False, False)
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
2679
 
(30, 30)
2680
 
>>> f = Person(name_max_length=20)
2681
 
>>> f['first_name'].field.max_length, f['last_name'].field.max_length
2682
 
(20, 20)
2683
 
>>> f = Person(name_max_length=None)
2684
 
>>> f['first_name'].field.max_length, f['last_name'].field.max_length
2685
 
(30, 30)
2686
 
 
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)
2697
 
>>> print p
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>
2701
 
>>> print p.as_ul()
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>
2705
 
>>> print p.as_p()
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>
2709
 
 
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')
2712
 
>>> print p
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>
2716
 
>>> print p.as_ul()
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>
2720
 
>>> print p.as_p()
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>
2724
 
 
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)
2730
 
>>> print p
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>
2735
 
>>> print p.as_ul()
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>
2740
 
>>> print p.as_p()
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>
2745
 
 
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" />
2753
 
>>> print p.as_ul()
2754
 
<input type="hidden" name="foo" /><input type="hidden" name="bar" />
2755
 
>>> print p.as_p()
2756
 
<input type="hidden" name="foo" /><input type="hidden" name="bar" />
2757
 
 
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)
2775
 
>>> print p
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>
2790
 
 
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)
2801
 
>>> print p.as_ul()
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>
2806
 
 
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
2809
 
in "attrs".
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)
2814
 
>>> print p.as_ul()
2815
 
<li>Username: <input type="text" name="username" maxlength="10" /></li>
2816
 
<li>Password: <input type="password" name="password" maxlength="10" /></li>
2817
 
 
2818
 
# Specifying labels ###########################################################
2819
 
 
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)
2828
 
>>> print p.as_ul()
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>
2832
 
 
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>
2853
 
 
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)
2859
 
>>> p.as_ul()
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>'
2861
 
 
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)
2867
 
>>> print p.as_ul()
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')
2871
 
>>> print p.as_ul()
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>
2874
 
 
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)
2881
 
>>> print p.as_ul()
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')
2885
 
>>> print p.as_ul()
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>
2888
 
 
2889
 
# Initial data ################################################################
2890
 
 
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)
2899
 
 
2900
 
Here, we're not submitting any data, so the initial value will be displayed.
2901
 
>>> p = UserRegistration(auto_id=False)
2902
 
>>> print p.as_ul()
2903
 
<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
2904
 
<li>Password: <input type="password" name="password" /></li>
2905
 
 
2906
 
Here, we're submitting data, so the initial value will *not* be displayed.
2907
 
>>> p = UserRegistration({}, auto_id=False)
2908
 
>>> print p.as_ul()
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)
2912
 
>>> print p.as_ul()
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)
2916
 
>>> print p.as_ul()
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>
2919
 
 
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'})
2924
 
>>> p.errors
2925
 
{'username': [u'This field is required.']}
2926
 
>>> p.is_valid()
2927
 
False
2928
 
 
2929
 
# Dynamic initial data ########################################################
2930
 
 
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.
2936
 
 
2937
 
>>> class UserRegistration(Form):
2938
 
...    username = CharField(max_length=10)
2939
 
...    password = CharField(widget=PasswordInput)
2940
 
 
2941
 
Here, we're not submitting any data, so the initial value will be displayed.
2942
 
>>> p = UserRegistration(initial={'username': 'django'}, auto_id=False)
2943
 
>>> print p.as_ul()
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)
2947
 
>>> print p.as_ul()
2948
 
<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
2949
 
<li>Password: <input type="password" name="password" /></li>
2950
 
 
2951
 
The 'initial' parameter is meaningless if you pass data.
2952
 
>>> p = UserRegistration({}, initial={'username': 'django'}, auto_id=False)
2953
 
>>> print p.as_ul()
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)
2957
 
>>> print p.as_ul()
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)
2961
 
>>> print p.as_ul()
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>
2964
 
 
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'})
2969
 
>>> p.errors
2970
 
{'username': [u'This field is required.']}
2971
 
>>> p.is_valid()
2972
 
False
2973
 
 
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)
2980
 
>>> print p.as_ul()
2981
 
<li>Username: <input type="text" name="username" value="babik" maxlength="10" /></li>
2982
 
<li>Password: <input type="password" name="password" /></li>
2983
 
 
2984
 
# Callable initial data ########################################################
2985
 
 
2986
 
The previous technique dealt with raw values as initial data, but it's also
2987
 
possible to specify callable data.
2988
 
 
2989
 
>>> class UserRegistration(Form):
2990
 
...    username = CharField(max_length=10)
2991
 
...    password = CharField(widget=PasswordInput)
2992
 
 
2993
 
We need to define functions that get called later.
2994
 
>>> def initial_django():
2995
 
...     return 'django'
2996
 
>>> def initial_stephane():
2997
 
...     return 'stephane'
2998
 
 
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)
3001
 
>>> print p.as_ul()
3002
 
<li>Username: <input type="text" name="username" value="django" maxlength="10" /></li>
3003
 
<li>Password: <input type="password" name="password" /></li>
3004
 
 
3005
 
The 'initial' parameter is meaningless if you pass data.
3006
 
>>> p = UserRegistration({}, initial={'username': initial_django}, auto_id=False)
3007
 
>>> print p.as_ul()
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)
3011
 
>>> print p.as_ul()
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)
3015
 
>>> print p.as_ul()
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>
3018
 
 
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})
3023
 
>>> p.errors
3024
 
{'username': [u'This field is required.']}
3025
 
>>> p.is_valid()
3026
 
False
3027
 
 
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)
3034
 
>>> print p.as_ul()
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)
3038
 
>>> print p.as_ul()
3039
 
<li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
3040
 
<li>Password: <input type="password" name="password" /></li>
3041
 
 
3042
 
# Help text ###################################################################
3043
 
 
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)
3050
 
>>> print p.as_ul()
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>
3053
 
>>> print p.as_p()
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>
3059
 
 
3060
 
The help text is displayed whether or not data is provided for the form.
3061
 
>>> p = UserRegistration({'username': u'foo'}, auto_id=False)
3062
 
>>> print p.as_ul()
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>
3065
 
 
3066
 
help_text is not displayed for hidden fields. It can be used for documentation
3067
 
purposes, though.
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)
3073
 
>>> print p.as_ul()
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>
3076
 
 
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)
3081
 
>>> p.as_ul()
3082
 
u'<li>Username: <input type="text" name="username" maxlength="10" /> \u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</li>'
3083
 
 
3084
 
# Subclassing forms ###########################################################
3085
 
 
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
3088
 
subclass.
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)
3096
 
>>> print p.as_ul()
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)
3101
 
>>> print m.as_ul()
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>
3106
 
 
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)
3118
 
>>> print b.as_ul()
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>
3124
 
 
3125
 
# Forms with prefixes #########################################################
3126
 
 
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
3133
 
actual field name.
3134
 
>>> class Person(Form):
3135
 
...     first_name = CharField()
3136
 
...     last_name = CharField()
3137
 
...     birthday = DateField()
3138
 
>>> data = {
3139
 
...     'person1-first_name': u'John',
3140
 
...     'person1-last_name': u'Lennon',
3141
 
...     'person1-birthday': u'1940-10-9'
3142
 
... }
3143
 
>>> p = Person(data, prefix='person1')
3144
 
>>> print p.as_ul()
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" />
3154
 
>>> p.errors
3155
 
{}
3156
 
>>> p.is_valid()
3157
 
True
3158
 
>>> p.cleaned_data
3159
 
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
3160
 
 
3161
 
Let's try submitting some bad data to make sure form.errors and field.errors
3162
 
work as expected.
3163
 
>>> data = {
3164
 
...     'person1-first_name': u'',
3165
 
...     'person1-last_name': u'',
3166
 
...     'person1-birthday': u''
3167
 
... }
3168
 
>>> p = Person(data, prefix='person1')
3169
 
>>> p.errors
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):
3175
 
...
3176
 
KeyError: "Key 'person1-first_name' not found in Form"
3177
 
 
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.
3180
 
>>> data = {
3181
 
...     'first_name': u'John',
3182
 
...     'last_name': u'Lennon',
3183
 
...     'birthday': u'1940-10-9'
3184
 
... }
3185
 
>>> p = Person(data, prefix='person1')
3186
 
>>> p.errors
3187
 
{'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']}
3188
 
 
3189
 
With prefixes, a single data dictionary can hold data for multiple instances
3190
 
of the same form.
3191
 
>>> data = {
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'
3198
 
... }
3199
 
>>> p1 = Person(data, prefix='person1')
3200
 
>>> p1.is_valid()
3201
 
True
3202
 
>>> p1.cleaned_data
3203
 
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
3204
 
>>> p2 = Person(data, prefix='person2')
3205
 
>>> p2.is_valid()
3206
 
True
3207
 
>>> p2.cleaned_data
3208
 
{'first_name': u'Jim', 'last_name': u'Morrison', 'birthday': datetime.date(1943, 12, 8)}
3209
 
 
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
3213
 
self.prefix.
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')
3221
 
>>> print p.as_ul()
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>
3225
 
>>> data = {
3226
 
...     'foo-prefix-first_name': u'John',
3227
 
...     'foo-prefix-last_name': u'Lennon',
3228
 
...     'foo-prefix-birthday': u'1940-10-9'
3229
 
... }
3230
 
>>> p = Person(data, prefix='foo')
3231
 
>>> p.is_valid()
3232
 
True
3233
 
>>> p.cleaned_data
3234
 
{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
3235
 
 
3236
 
# Forms with NullBooleanFields ################################################
3237
 
 
3238
 
NullBooleanField is a bit of a special case because its presentation (widget)
3239
 
is different than its data. This is handled transparently, though.
3240
 
 
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>
3250
 
</select>
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>
3257
 
</select>
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>
3264
 
</select>
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>
3271
 
</select>
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>
3278
 
</select>
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>
3285
 
</select>
3286
 
 
3287
 
# Forms with FileFields ################################################
3288
 
 
3289
 
FileFields are a special case because they take their data from the request.FILES,
3290
 
not request.POST. 
3291
 
 
3292
 
>>> class FileForm(Form):
3293
 
...     file1 = FileField()
3294
 
>>> f = FileForm(auto_id=False)
3295
 
>>> print f
3296
 
<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>
3297
 
 
3298
 
>>> f = FileForm(data={}, files={}, auto_id=False)
3299
 
>>> print f
3300
 
<tr><th>File1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="file" name="file1" /></td></tr>
3301
 
 
3302
 
>>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':''}}, auto_id=False)
3303
 
>>> print f
3304
 
<tr><th>File1:</th><td><ul class="errorlist"><li>The submitted file is empty.</li></ul><input type="file" name="file1" /></td></tr>
3305
 
 
3306
 
>>> f = FileForm(data={}, files={'file1': 'something that is not a file'}, auto_id=False)
3307
 
>>> print f
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>
3309
 
 
3310
 
>>> f = FileForm(data={}, files={'file1': {'filename': 'name', 'content':'some content'}}, auto_id=False)
3311
 
>>> print f
3312
 
<tr><th>File1:</th><td><input type="file" name="file1" /></td></tr>
3313
 
>>> f.is_valid()
3314
 
True
3315
 
 
3316
 
# Basic form processing in a view #############################################
3317
 
 
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)
3330
 
...     else:
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}))
3336
 
 
3337
 
Case 1: GET (an empty form, with no errors).
3338
 
>>> print my_function('GET', {})
3339
 
<form action="" method="post">
3340
 
<table>
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>
3344
 
</table>
3345
 
<input type="submit" />
3346
 
</form>
3347
 
 
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">
3351
 
<table>
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>
3356
 
</table>
3357
 
<input type="submit" />
3358
 
</form>
3359
 
 
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'}
3363
 
 
3364
 
# Some ideas for using templates with forms ###################################
3365
 
 
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
3374
 
 
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
3379
 
particular field.
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" />
3385
 
... </form>''')
3386
 
>>> print t.render(Context({'form': UserRegistration(auto_id=False)}))
3387
 
<form action="">
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" />
3392
 
</form>
3393
 
>>> print t.render(Context({'form': UserRegistration({'username': 'django'}, auto_id=False)}))
3394
 
<form action="">
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" />
3399
 
</form>
3400
 
 
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" />
3410
 
... </form>''')
3411
 
>>> print t.render(Context({'form': UserRegistration(auto_id=False)}))
3412
 
<form action="">
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" />
3417
 
</form>
3418
 
 
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" />
3428
 
... </form>''')
3429
 
>>> print t.render(Context({'form': UserRegistration(auto_id=False)}))
3430
 
<form action="">
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" />
3435
 
</form>
3436
 
>>> print t.render(Context({'form': UserRegistration(auto_id='id_%s')}))
3437
 
<form action="">
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" />
3442
 
</form>
3443
 
 
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" />
3451
 
... </form>''')
3452
 
>>> print t.render(Context({'form': UserRegistration(auto_id=False)}))
3453
 
<form action="">
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" />
3458
 
</form>
3459
 
>>> Template('{{ form.password1.help_text }}').render(Context({'form': UserRegistration(auto_id=False)}))
3460
 
u''
3461
 
 
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')
3465
 
>>> for bf in f:
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>
3470
 
 
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" />
3480
 
... </form>''')
3481
 
>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)}))
3482
 
<form action="">
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" />
3487
 
</form>
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" />
3494
 
... </form>''')
3495
 
>>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)}))
3496
 
<form action="">
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" />
3502
 
</form>
3503
 
 
3504
 
###############
3505
 
# Extra stuff #
3506
 
###############
3507
 
 
3508
 
The newforms library comes with some extra, higher-level Field and Widget
3509
 
classes that demonstrate some of the library's abilities.
3510
 
 
3511
 
# SelectDateWidget ############################################################
3512
 
 
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>
3529
 
</select>
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>
3562
 
</select>
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>
3574
 
</select>
3575
 
>>> w.render('mydate', None) == w.render('mydate', '')
3576
 
True
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>
3591
 
</select>
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>
3624
 
</select>
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>
3636
 
</select>
3637
 
 
3638
 
Using a SelectDateWidget in a form:
3639
 
 
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()
3644
 
True
3645
 
>>> print a.cleaned_data['mydate']
3646
 
2008-04-01
3647
 
 
3648
 
As with any widget that implements get_value_from_datadict,
3649
 
we must be prepared to accept the input from the "as_hidden"
3650
 
rendering as well.
3651
 
 
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()
3656
 
True
3657
 
>>> print b.cleaned_data['mydate']
3658
 
2008-04-01
3659
 
 
3660
 
 
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.
3666
 
 
3667
 
>>> class ComplexMultiWidget(MultiWidget):
3668
 
...     def __init__(self, attrs=None):
3669
 
...         widgets = (
3670
 
...             TextInput(),
3671
 
...             SelectMultiple(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
3672
 
...             SplitDateTimeWidget(),
3673
 
...         )
3674
 
...         super(ComplexMultiWidget, self).__init__(widgets, attrs)
3675
 
...
3676
 
...     def decompress(self, value):
3677
 
...         if 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>
3691
 
</select>
3692
 
<input type="text" name="name_2_0" value="2007-04-25" /><input type="text" name="name_2_1" value="06:24:00" />
3693
 
 
3694
 
>>> class ComplexField(MultiValueField):
3695
 
...     def __init__(self, required=True, widget=None, label=None, initial=None):
3696
 
...         fields = (
3697
 
...             CharField(),
3698
 
...             MultipleChoiceField(choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))),
3699
 
...             SplitDateTimeField()
3700
 
...         )
3701
 
...         super(ComplexField, self).__init__(fields, required, widget, label, initial)
3702
 
...
3703
 
...     def compress(self, data_list):
3704
 
...         if data_list:
3705
 
...             return '%s,%s,%s' % (data_list[0],''.join(data_list[1]),data_list[2])
3706
 
...         return None
3707
 
 
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):
3713
 
...
3714
 
ValidationError: [u'Select a valid choice. X is not one of the available choices.']
3715
 
 
3716
 
# If insufficient data is provided, None is substituted
3717
 
>>> f.clean(['some text',['JP']])
3718
 
Traceback (most recent call last):
3719
 
...
3720
 
ValidationError: [u'This field is required.']
3721
 
 
3722
 
>>> class ComplexFieldForm(Form):
3723
 
...     field1 = ComplexField(widget=w)
3724
 
>>> f = ComplexFieldForm()
3725
 
>>> print f
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>
3732
 
</select>
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>
3734
 
 
3735
 
>>> f = ComplexFieldForm({'field1_0':'some text','field1_1':['J','P'], 'field1_2_0':'2007-04-25', 'field1_2_1':'06:24:00'})
3736
 
>>> print f
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>
3743
 
</select>
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>
3745
 
 
3746
 
>>> f.cleaned_data
3747
 
{'field1': u'some text,JP,2007-04-25 06:24:00'}
3748
 
 
3749
 
#################################
3750
 
# Tests of underlying functions #
3751
 
#################################
3752
 
 
3753
 
# smart_unicode tests
3754
 
>>> from django.utils.encoding import smart_unicode
3755
 
>>> class Test:
3756
 
...     def __str__(self):
3757
 
...        return 'ŠĐĆŽćžšđ'
3758
 
>>> class TestU:
3759
 
...     def __str__(self):
3760
 
...        return 'Foo'
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)
3768
 
u'1'
3769
 
>>> smart_unicode('foo')
3770
 
u'foo'
3771
 
 
3772
 
# flatatt tests
3773
 
>>> from django.newforms.util import flatatt
3774
 
>>> flatatt({'id': "header"})
3775
 
u' id="header"'
3776
 
>>> flatatt({'class': "news", 'title': "Read this"})
3777
 
u' class="news" title="Read this"'
3778
 
>>> flatatt({})
3779
 
u''
3780
 
 
3781
 
####################################
3782
 
# Test accessing errors in clean() #
3783
 
####################################
3784
 
 
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()
3792
 
...         return data
3793
 
 
3794
 
>>> f = UserForm({'username': 'SirRobin', 'password': 'blue'})
3795
 
>>> f.is_valid()
3796
 
True
3797
 
>>> f.cleaned_data['username']
3798
 
u'sirrobin'
3799
 
"""
 
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
3800
28
 
3801
29
__test__ = {
 
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,
3805
56
}
3806
57
 
3807
58
if __name__ == "__main__":