1 # -*- coding: utf-8 -*- |
|
2 r""" |
|
3 >>> from django.newforms import * |
|
4 >>> import datetime |
|
5 >>> import re |
|
6 |
|
7 ########### |
|
8 # Widgets # |
|
9 ########### |
|
10 |
|
11 Each Widget class corresponds to an HTML form widget. A Widget knows how to |
|
12 render itself, given a field name and some data. Widgets don't perform |
|
13 validation. |
|
14 |
|
15 # TextInput Widget ############################################################ |
|
16 |
|
17 >>> w = TextInput() |
|
18 >>> w.render('email', '') |
|
19 u'<input type="text" name="email" />' |
|
20 >>> w.render('email', None) |
|
21 u'<input type="text" name="email" />' |
|
22 >>> w.render('email', 'test@example.com') |
|
23 u'<input type="text" name="email" value="test@example.com" />' |
|
24 >>> w.render('email', 'some "quoted" & ampersanded value') |
|
25 u'<input type="text" name="email" value="some "quoted" & ampersanded value" />' |
|
26 >>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) |
|
27 u'<input type="text" name="email" value="test@example.com" class="fun" />' |
|
28 |
|
29 # Note that doctest in Python 2.4 (and maybe 2.5?) doesn't support non-ascii |
|
30 # characters in output, so we're displaying the repr() here. |
|
31 >>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) |
|
32 u'<input type="text" name="email" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" class="fun" />' |
|
33 |
|
34 You can also pass 'attrs' to the constructor: |
|
35 >>> w = TextInput(attrs={'class': 'fun'}) |
|
36 >>> w.render('email', '') |
|
37 u'<input type="text" class="fun" name="email" />' |
|
38 >>> w.render('email', 'foo@example.com') |
|
39 u'<input type="text" class="fun" value="foo@example.com" name="email" />' |
|
40 |
|
41 'attrs' passed to render() get precedence over those passed to the constructor: |
|
42 >>> w = TextInput(attrs={'class': 'pretty'}) |
|
43 >>> w.render('email', '', attrs={'class': 'special'}) |
|
44 u'<input type="text" class="special" name="email" />' |
|
45 |
|
46 # PasswordInput Widget ############################################################ |
|
47 |
|
48 >>> w = PasswordInput() |
|
49 >>> w.render('email', '') |
|
50 u'<input type="password" name="email" />' |
|
51 >>> w.render('email', None) |
|
52 u'<input type="password" name="email" />' |
|
53 >>> w.render('email', 'test@example.com') |
|
54 u'<input type="password" name="email" value="test@example.com" />' |
|
55 >>> w.render('email', 'some "quoted" & ampersanded value') |
|
56 u'<input type="password" name="email" value="some "quoted" & ampersanded value" />' |
|
57 >>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) |
|
58 u'<input type="password" name="email" value="test@example.com" class="fun" />' |
|
59 |
|
60 You can also pass 'attrs' to the constructor: |
|
61 >>> w = PasswordInput(attrs={'class': 'fun'}) |
|
62 >>> w.render('email', '') |
|
63 u'<input type="password" class="fun" name="email" />' |
|
64 >>> w.render('email', 'foo@example.com') |
|
65 u'<input type="password" class="fun" value="foo@example.com" name="email" />' |
|
66 |
|
67 'attrs' passed to render() get precedence over those passed to the constructor: |
|
68 >>> w = PasswordInput(attrs={'class': 'pretty'}) |
|
69 >>> w.render('email', '', attrs={'class': 'special'}) |
|
70 u'<input type="password" class="special" name="email" />' |
|
71 |
|
72 >>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) |
|
73 u'<input type="password" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' |
|
74 |
|
75 The render_value argument lets you specify whether the widget should render |
|
76 its value. You may want to do this for security reasons. |
|
77 >>> w = PasswordInput(render_value=True) |
|
78 >>> w.render('email', 'secret') |
|
79 u'<input type="password" name="email" value="secret" />' |
|
80 >>> w = PasswordInput(render_value=False) |
|
81 >>> w.render('email', '') |
|
82 u'<input type="password" name="email" />' |
|
83 >>> w.render('email', None) |
|
84 u'<input type="password" name="email" />' |
|
85 >>> w.render('email', 'secret') |
|
86 u'<input type="password" name="email" />' |
|
87 >>> w = PasswordInput(attrs={'class': 'fun'}, render_value=False) |
|
88 >>> w.render('email', 'secret') |
|
89 u'<input type="password" class="fun" name="email" />' |
|
90 |
|
91 # HiddenInput Widget ############################################################ |
|
92 |
|
93 >>> w = HiddenInput() |
|
94 >>> w.render('email', '') |
|
95 u'<input type="hidden" name="email" />' |
|
96 >>> w.render('email', None) |
|
97 u'<input type="hidden" name="email" />' |
|
98 >>> w.render('email', 'test@example.com') |
|
99 u'<input type="hidden" name="email" value="test@example.com" />' |
|
100 >>> w.render('email', 'some "quoted" & ampersanded value') |
|
101 u'<input type="hidden" name="email" value="some "quoted" & ampersanded value" />' |
|
102 >>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) |
|
103 u'<input type="hidden" name="email" value="test@example.com" class="fun" />' |
|
104 |
|
105 You can also pass 'attrs' to the constructor: |
|
106 >>> w = HiddenInput(attrs={'class': 'fun'}) |
|
107 >>> w.render('email', '') |
|
108 u'<input type="hidden" class="fun" name="email" />' |
|
109 >>> w.render('email', 'foo@example.com') |
|
110 u'<input type="hidden" class="fun" value="foo@example.com" name="email" />' |
|
111 |
|
112 'attrs' passed to render() get precedence over those passed to the constructor: |
|
113 >>> w = HiddenInput(attrs={'class': 'pretty'}) |
|
114 >>> w.render('email', '', attrs={'class': 'special'}) |
|
115 u'<input type="hidden" class="special" name="email" />' |
|
116 |
|
117 >>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) |
|
118 u'<input type="hidden" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' |
|
119 |
|
120 'attrs' passed to render() get precedence over those passed to the constructor: |
|
121 >>> w = HiddenInput(attrs={'class': 'pretty'}) |
|
122 >>> w.render('email', '', attrs={'class': 'special'}) |
|
123 u'<input type="hidden" class="special" name="email" />' |
|
124 |
|
125 # MultipleHiddenInput Widget ################################################## |
|
126 |
|
127 >>> w = MultipleHiddenInput() |
|
128 >>> w.render('email', []) |
|
129 u'' |
|
130 >>> w.render('email', None) |
|
131 u'' |
|
132 >>> w.render('email', ['test@example.com']) |
|
133 u'<input type="hidden" name="email" value="test@example.com" />' |
|
134 >>> w.render('email', ['some "quoted" & ampersanded value']) |
|
135 u'<input type="hidden" name="email" value="some "quoted" & ampersanded value" />' |
|
136 >>> w.render('email', ['test@example.com', 'foo@example.com']) |
|
137 u'<input type="hidden" name="email" value="test@example.com" />\n<input type="hidden" name="email" value="foo@example.com" />' |
|
138 >>> w.render('email', ['test@example.com'], attrs={'class': 'fun'}) |
|
139 u'<input type="hidden" name="email" value="test@example.com" class="fun" />' |
|
140 >>> w.render('email', ['test@example.com', 'foo@example.com'], attrs={'class': 'fun'}) |
|
141 u'<input type="hidden" name="email" value="test@example.com" class="fun" />\n<input type="hidden" name="email" value="foo@example.com" class="fun" />' |
|
142 |
|
143 You can also pass 'attrs' to the constructor: |
|
144 >>> w = MultipleHiddenInput(attrs={'class': 'fun'}) |
|
145 >>> w.render('email', []) |
|
146 u'' |
|
147 >>> w.render('email', ['foo@example.com']) |
|
148 u'<input type="hidden" class="fun" value="foo@example.com" name="email" />' |
|
149 >>> w.render('email', ['foo@example.com', 'test@example.com']) |
|
150 u'<input type="hidden" class="fun" value="foo@example.com" name="email" />\n<input type="hidden" class="fun" value="test@example.com" name="email" />' |
|
151 |
|
152 'attrs' passed to render() get precedence over those passed to the constructor: |
|
153 >>> w = MultipleHiddenInput(attrs={'class': 'pretty'}) |
|
154 >>> w.render('email', ['foo@example.com'], attrs={'class': 'special'}) |
|
155 u'<input type="hidden" class="special" value="foo@example.com" name="email" />' |
|
156 |
|
157 >>> w.render('email', ['ŠĐĆŽćžšđ'], attrs={'class': 'fun'}) |
|
158 u'<input type="hidden" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' |
|
159 |
|
160 'attrs' passed to render() get precedence over those passed to the constructor: |
|
161 >>> w = MultipleHiddenInput(attrs={'class': 'pretty'}) |
|
162 >>> w.render('email', ['foo@example.com'], attrs={'class': 'special'}) |
|
163 u'<input type="hidden" class="special" value="foo@example.com" name="email" />' |
|
164 |
|
165 # FileInput Widget ############################################################ |
|
166 |
|
167 >>> w = FileInput() |
|
168 >>> w.render('email', '') |
|
169 u'<input type="file" name="email" />' |
|
170 >>> w.render('email', None) |
|
171 u'<input type="file" name="email" />' |
|
172 >>> w.render('email', 'test@example.com') |
|
173 u'<input type="file" name="email" value="test@example.com" />' |
|
174 >>> w.render('email', 'some "quoted" & ampersanded value') |
|
175 u'<input type="file" name="email" value="some "quoted" & ampersanded value" />' |
|
176 >>> w.render('email', 'test@example.com', attrs={'class': 'fun'}) |
|
177 u'<input type="file" name="email" value="test@example.com" class="fun" />' |
|
178 |
|
179 You can also pass 'attrs' to the constructor: |
|
180 >>> w = FileInput(attrs={'class': 'fun'}) |
|
181 >>> w.render('email', '') |
|
182 u'<input type="file" class="fun" name="email" />' |
|
183 >>> w.render('email', 'foo@example.com') |
|
184 u'<input type="file" class="fun" value="foo@example.com" name="email" />' |
|
185 |
|
186 >>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) |
|
187 u'<input type="file" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />' |
|
188 |
|
189 # Textarea Widget ############################################################# |
|
190 |
|
191 >>> w = Textarea() |
|
192 >>> w.render('msg', '') |
|
193 u'<textarea name="msg"></textarea>' |
|
194 >>> w.render('msg', None) |
|
195 u'<textarea name="msg"></textarea>' |
|
196 >>> w.render('msg', 'value') |
|
197 u'<textarea name="msg">value</textarea>' |
|
198 >>> w.render('msg', 'some "quoted" & ampersanded value') |
|
199 u'<textarea name="msg">some "quoted" & ampersanded value</textarea>' |
|
200 >>> w.render('msg', 'value', attrs={'class': 'pretty'}) |
|
201 u'<textarea name="msg" class="pretty">value</textarea>' |
|
202 |
|
203 You can also pass 'attrs' to the constructor: |
|
204 >>> w = Textarea(attrs={'class': 'pretty'}) |
|
205 >>> w.render('msg', '') |
|
206 u'<textarea class="pretty" name="msg"></textarea>' |
|
207 >>> w.render('msg', 'example') |
|
208 u'<textarea class="pretty" name="msg">example</textarea>' |
|
209 |
|
210 'attrs' passed to render() get precedence over those passed to the constructor: |
|
211 >>> w = Textarea(attrs={'class': 'pretty'}) |
|
212 >>> w.render('msg', '', attrs={'class': 'special'}) |
|
213 u'<textarea class="special" name="msg"></textarea>' |
|
214 |
|
215 >>> w.render('msg', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'}) |
|
216 u'<textarea class="fun" name="msg">\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</textarea>' |
|
217 |
|
218 # CheckboxInput Widget ######################################################## |
|
219 |
|
220 >>> w = CheckboxInput() |
|
221 >>> w.render('is_cool', '') |
|
222 u'<input type="checkbox" name="is_cool" />' |
|
223 >>> w.render('is_cool', None) |
|
224 u'<input type="checkbox" name="is_cool" />' |
|
225 >>> w.render('is_cool', False) |
|
226 u'<input type="checkbox" name="is_cool" />' |
|
227 >>> w.render('is_cool', True) |
|
228 u'<input checked="checked" type="checkbox" name="is_cool" />' |
|
229 |
|
230 Using any value that's not in ('', None, False, True) will check the checkbox |
|
231 and set the 'value' attribute. |
|
232 >>> w.render('is_cool', 'foo') |
|
233 u'<input checked="checked" type="checkbox" name="is_cool" value="foo" />' |
|
234 |
|
235 >>> w.render('is_cool', False, attrs={'class': 'pretty'}) |
|
236 u'<input type="checkbox" name="is_cool" class="pretty" />' |
|
237 |
|
238 You can also pass 'attrs' to the constructor: |
|
239 >>> w = CheckboxInput(attrs={'class': 'pretty'}) |
|
240 >>> w.render('is_cool', '') |
|
241 u'<input type="checkbox" class="pretty" name="is_cool" />' |
|
242 |
|
243 'attrs' passed to render() get precedence over those passed to the constructor: |
|
244 >>> w = CheckboxInput(attrs={'class': 'pretty'}) |
|
245 >>> w.render('is_cool', '', attrs={'class': 'special'}) |
|
246 u'<input type="checkbox" class="special" name="is_cool" />' |
|
247 |
|
248 You can pass 'check_test' to the constructor. This is a callable that takes the |
|
249 value and returns True if the box should be checked. |
|
250 >>> w = CheckboxInput(check_test=lambda value: value.startswith('hello')) |
|
251 >>> w.render('greeting', '') |
|
252 u'<input type="checkbox" name="greeting" />' |
|
253 >>> w.render('greeting', 'hello') |
|
254 u'<input checked="checked" type="checkbox" name="greeting" value="hello" />' |
|
255 >>> w.render('greeting', 'hello there') |
|
256 u'<input checked="checked" type="checkbox" name="greeting" value="hello there" />' |
|
257 >>> w.render('greeting', 'hello & goodbye') |
|
258 u'<input checked="checked" type="checkbox" name="greeting" value="hello & goodbye" />' |
|
259 |
|
260 A subtlety: If the 'check_test' argument cannot handle a value and raises any |
|
261 exception during its __call__, then the exception will be swallowed and the box |
|
262 will not be checked. In this example, the 'check_test' assumes the value has a |
|
263 startswith() method, which fails for the values True, False and None. |
|
264 >>> w.render('greeting', True) |
|
265 u'<input type="checkbox" name="greeting" />' |
|
266 >>> w.render('greeting', False) |
|
267 u'<input type="checkbox" name="greeting" />' |
|
268 >>> w.render('greeting', None) |
|
269 u'<input type="checkbox" name="greeting" />' |
|
270 |
|
271 # Select Widget ############################################################### |
|
272 |
|
273 >>> w = Select() |
|
274 >>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
275 <select name="beatle"> |
|
276 <option value="J" selected="selected">John</option> |
|
277 <option value="P">Paul</option> |
|
278 <option value="G">George</option> |
|
279 <option value="R">Ringo</option> |
|
280 </select> |
|
281 |
|
282 If the value is None, none of the options are selected: |
|
283 >>> print w.render('beatle', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
284 <select name="beatle"> |
|
285 <option value="J">John</option> |
|
286 <option value="P">Paul</option> |
|
287 <option value="G">George</option> |
|
288 <option value="R">Ringo</option> |
|
289 </select> |
|
290 |
|
291 If the value corresponds to a label (but not to an option value), none of the options are selected: |
|
292 >>> print w.render('beatle', 'John', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
293 <select name="beatle"> |
|
294 <option value="J">John</option> |
|
295 <option value="P">Paul</option> |
|
296 <option value="G">George</option> |
|
297 <option value="R">Ringo</option> |
|
298 </select> |
|
299 |
|
300 The value is compared to its str(): |
|
301 >>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')]) |
|
302 <select name="num"> |
|
303 <option value="1">1</option> |
|
304 <option value="2" selected="selected">2</option> |
|
305 <option value="3">3</option> |
|
306 </select> |
|
307 >>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)]) |
|
308 <select name="num"> |
|
309 <option value="1">1</option> |
|
310 <option value="2" selected="selected">2</option> |
|
311 <option value="3">3</option> |
|
312 </select> |
|
313 >>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)]) |
|
314 <select name="num"> |
|
315 <option value="1">1</option> |
|
316 <option value="2" selected="selected">2</option> |
|
317 <option value="3">3</option> |
|
318 </select> |
|
319 |
|
320 The 'choices' argument can be any iterable: |
|
321 >>> from itertools import chain |
|
322 >>> def get_choices(): |
|
323 ... for i in range(5): |
|
324 ... yield (i, i) |
|
325 >>> print w.render('num', 2, choices=get_choices()) |
|
326 <select name="num"> |
|
327 <option value="0">0</option> |
|
328 <option value="1">1</option> |
|
329 <option value="2" selected="selected">2</option> |
|
330 <option value="3">3</option> |
|
331 <option value="4">4</option> |
|
332 </select> |
|
333 >>> things = ({'id': 1, 'name': 'And Boom'}, {'id': 2, 'name': 'One More Thing!'}) |
|
334 >>> class SomeForm(Form): |
|
335 ... somechoice = ChoiceField(choices=chain((('', '-'*9),), [(thing['id'], thing['name']) for thing in things])) |
|
336 >>> f = SomeForm() |
|
337 >>> f.as_table() |
|
338 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>' |
|
339 >>> f.as_table() |
|
340 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>' |
|
341 >>> f = SomeForm({'somechoice': 2}) |
|
342 >>> f.as_table() |
|
343 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>' |
|
344 |
|
345 You can also pass 'choices' to the constructor: |
|
346 >>> w = Select(choices=[(1, 1), (2, 2), (3, 3)]) |
|
347 >>> print w.render('num', 2) |
|
348 <select name="num"> |
|
349 <option value="1">1</option> |
|
350 <option value="2" selected="selected">2</option> |
|
351 <option value="3">3</option> |
|
352 </select> |
|
353 |
|
354 If 'choices' is passed to both the constructor and render(), then they'll both be in the output: |
|
355 >>> print w.render('num', 2, choices=[(4, 4), (5, 5)]) |
|
356 <select name="num"> |
|
357 <option value="1">1</option> |
|
358 <option value="2" selected="selected">2</option> |
|
359 <option value="3">3</option> |
|
360 <option value="4">4</option> |
|
361 <option value="5">5</option> |
|
362 </select> |
|
363 |
|
364 >>> w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) |
|
365 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>' |
|
366 |
|
367 If choices is passed to the constructor and is a generator, it can be iterated |
|
368 over multiple times without getting consumed: |
|
369 >>> w = Select(choices=get_choices()) |
|
370 >>> print w.render('num', 2) |
|
371 <select name="num"> |
|
372 <option value="0">0</option> |
|
373 <option value="1">1</option> |
|
374 <option value="2" selected="selected">2</option> |
|
375 <option value="3">3</option> |
|
376 <option value="4">4</option> |
|
377 </select> |
|
378 >>> print w.render('num', 3) |
|
379 <select name="num"> |
|
380 <option value="0">0</option> |
|
381 <option value="1">1</option> |
|
382 <option value="2">2</option> |
|
383 <option value="3" selected="selected">3</option> |
|
384 <option value="4">4</option> |
|
385 </select> |
|
386 |
|
387 # NullBooleanSelect Widget #################################################### |
|
388 |
|
389 >>> w = NullBooleanSelect() |
|
390 >>> print w.render('is_cool', True) |
|
391 <select name="is_cool"> |
|
392 <option value="1">Unknown</option> |
|
393 <option value="2" selected="selected">Yes</option> |
|
394 <option value="3">No</option> |
|
395 </select> |
|
396 >>> print w.render('is_cool', False) |
|
397 <select name="is_cool"> |
|
398 <option value="1">Unknown</option> |
|
399 <option value="2">Yes</option> |
|
400 <option value="3" selected="selected">No</option> |
|
401 </select> |
|
402 >>> print w.render('is_cool', None) |
|
403 <select name="is_cool"> |
|
404 <option value="1" selected="selected">Unknown</option> |
|
405 <option value="2">Yes</option> |
|
406 <option value="3">No</option> |
|
407 </select> |
|
408 >>> print w.render('is_cool', '2') |
|
409 <select name="is_cool"> |
|
410 <option value="1">Unknown</option> |
|
411 <option value="2" selected="selected">Yes</option> |
|
412 <option value="3">No</option> |
|
413 </select> |
|
414 >>> print w.render('is_cool', '3') |
|
415 <select name="is_cool"> |
|
416 <option value="1">Unknown</option> |
|
417 <option value="2">Yes</option> |
|
418 <option value="3" selected="selected">No</option> |
|
419 </select> |
|
420 |
|
421 # SelectMultiple Widget ####################################################### |
|
422 |
|
423 >>> w = SelectMultiple() |
|
424 >>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
425 <select multiple="multiple" name="beatles"> |
|
426 <option value="J" selected="selected">John</option> |
|
427 <option value="P">Paul</option> |
|
428 <option value="G">George</option> |
|
429 <option value="R">Ringo</option> |
|
430 </select> |
|
431 >>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
432 <select multiple="multiple" name="beatles"> |
|
433 <option value="J" selected="selected">John</option> |
|
434 <option value="P" selected="selected">Paul</option> |
|
435 <option value="G">George</option> |
|
436 <option value="R">Ringo</option> |
|
437 </select> |
|
438 >>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
439 <select multiple="multiple" name="beatles"> |
|
440 <option value="J" selected="selected">John</option> |
|
441 <option value="P" selected="selected">Paul</option> |
|
442 <option value="G">George</option> |
|
443 <option value="R" selected="selected">Ringo</option> |
|
444 </select> |
|
445 |
|
446 If the value is None, none of the options are selected: |
|
447 >>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
448 <select multiple="multiple" name="beatles"> |
|
449 <option value="J">John</option> |
|
450 <option value="P">Paul</option> |
|
451 <option value="G">George</option> |
|
452 <option value="R">Ringo</option> |
|
453 </select> |
|
454 |
|
455 If the value corresponds to a label (but not to an option value), none of the options are selected: |
|
456 >>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
457 <select multiple="multiple" name="beatles"> |
|
458 <option value="J">John</option> |
|
459 <option value="P">Paul</option> |
|
460 <option value="G">George</option> |
|
461 <option value="R">Ringo</option> |
|
462 </select> |
|
463 |
|
464 If multiple values are given, but some of them are not valid, the valid ones are selected: |
|
465 >>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
466 <select multiple="multiple" name="beatles"> |
|
467 <option value="J" selected="selected">John</option> |
|
468 <option value="P">Paul</option> |
|
469 <option value="G" selected="selected">George</option> |
|
470 <option value="R">Ringo</option> |
|
471 </select> |
|
472 |
|
473 The value is compared to its str(): |
|
474 >>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')]) |
|
475 <select multiple="multiple" name="nums"> |
|
476 <option value="1">1</option> |
|
477 <option value="2" selected="selected">2</option> |
|
478 <option value="3">3</option> |
|
479 </select> |
|
480 >>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)]) |
|
481 <select multiple="multiple" name="nums"> |
|
482 <option value="1">1</option> |
|
483 <option value="2" selected="selected">2</option> |
|
484 <option value="3">3</option> |
|
485 </select> |
|
486 >>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)]) |
|
487 <select multiple="multiple" name="nums"> |
|
488 <option value="1">1</option> |
|
489 <option value="2" selected="selected">2</option> |
|
490 <option value="3">3</option> |
|
491 </select> |
|
492 |
|
493 The 'choices' argument can be any iterable: |
|
494 >>> def get_choices(): |
|
495 ... for i in range(5): |
|
496 ... yield (i, i) |
|
497 >>> print w.render('nums', [2], choices=get_choices()) |
|
498 <select multiple="multiple" name="nums"> |
|
499 <option value="0">0</option> |
|
500 <option value="1">1</option> |
|
501 <option value="2" selected="selected">2</option> |
|
502 <option value="3">3</option> |
|
503 <option value="4">4</option> |
|
504 </select> |
|
505 |
|
506 You can also pass 'choices' to the constructor: |
|
507 >>> w = SelectMultiple(choices=[(1, 1), (2, 2), (3, 3)]) |
|
508 >>> print w.render('nums', [2]) |
|
509 <select multiple="multiple" name="nums"> |
|
510 <option value="1">1</option> |
|
511 <option value="2" selected="selected">2</option> |
|
512 <option value="3">3</option> |
|
513 </select> |
|
514 |
|
515 If 'choices' is passed to both the constructor and render(), then they'll both be in the output: |
|
516 >>> print w.render('nums', [2], choices=[(4, 4), (5, 5)]) |
|
517 <select multiple="multiple" name="nums"> |
|
518 <option value="1">1</option> |
|
519 <option value="2" selected="selected">2</option> |
|
520 <option value="3">3</option> |
|
521 <option value="4">4</option> |
|
522 <option value="5">5</option> |
|
523 </select> |
|
524 |
|
525 >>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) |
|
526 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>' |
|
527 |
|
528 # RadioSelect Widget ########################################################## |
|
529 |
|
530 >>> w = RadioSelect() |
|
531 >>> print w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
532 <ul> |
|
533 <li><label><input checked="checked" type="radio" name="beatle" value="J" /> John</label></li> |
|
534 <li><label><input type="radio" name="beatle" value="P" /> Paul</label></li> |
|
535 <li><label><input type="radio" name="beatle" value="G" /> George</label></li> |
|
536 <li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li> |
|
537 </ul> |
|
538 |
|
539 If the value is None, none of the options are checked: |
|
540 >>> print w.render('beatle', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
541 <ul> |
|
542 <li><label><input type="radio" name="beatle" value="J" /> John</label></li> |
|
543 <li><label><input type="radio" name="beatle" value="P" /> Paul</label></li> |
|
544 <li><label><input type="radio" name="beatle" value="G" /> George</label></li> |
|
545 <li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li> |
|
546 </ul> |
|
547 |
|
548 If the value corresponds to a label (but not to an option value), none of the options are checked: |
|
549 >>> print w.render('beatle', 'John', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
550 <ul> |
|
551 <li><label><input type="radio" name="beatle" value="J" /> John</label></li> |
|
552 <li><label><input type="radio" name="beatle" value="P" /> Paul</label></li> |
|
553 <li><label><input type="radio" name="beatle" value="G" /> George</label></li> |
|
554 <li><label><input type="radio" name="beatle" value="R" /> Ringo</label></li> |
|
555 </ul> |
|
556 |
|
557 The value is compared to its str(): |
|
558 >>> print w.render('num', 2, choices=[('1', '1'), ('2', '2'), ('3', '3')]) |
|
559 <ul> |
|
560 <li><label><input type="radio" name="num" value="1" /> 1</label></li> |
|
561 <li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> |
|
562 <li><label><input type="radio" name="num" value="3" /> 3</label></li> |
|
563 </ul> |
|
564 >>> print w.render('num', '2', choices=[(1, 1), (2, 2), (3, 3)]) |
|
565 <ul> |
|
566 <li><label><input type="radio" name="num" value="1" /> 1</label></li> |
|
567 <li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> |
|
568 <li><label><input type="radio" name="num" value="3" /> 3</label></li> |
|
569 </ul> |
|
570 >>> print w.render('num', 2, choices=[(1, 1), (2, 2), (3, 3)]) |
|
571 <ul> |
|
572 <li><label><input type="radio" name="num" value="1" /> 1</label></li> |
|
573 <li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> |
|
574 <li><label><input type="radio" name="num" value="3" /> 3</label></li> |
|
575 </ul> |
|
576 |
|
577 The 'choices' argument can be any iterable: |
|
578 >>> def get_choices(): |
|
579 ... for i in range(5): |
|
580 ... yield (i, i) |
|
581 >>> print w.render('num', 2, choices=get_choices()) |
|
582 <ul> |
|
583 <li><label><input type="radio" name="num" value="0" /> 0</label></li> |
|
584 <li><label><input type="radio" name="num" value="1" /> 1</label></li> |
|
585 <li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> |
|
586 <li><label><input type="radio" name="num" value="3" /> 3</label></li> |
|
587 <li><label><input type="radio" name="num" value="4" /> 4</label></li> |
|
588 </ul> |
|
589 |
|
590 You can also pass 'choices' to the constructor: |
|
591 >>> w = RadioSelect(choices=[(1, 1), (2, 2), (3, 3)]) |
|
592 >>> print w.render('num', 2) |
|
593 <ul> |
|
594 <li><label><input type="radio" name="num" value="1" /> 1</label></li> |
|
595 <li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> |
|
596 <li><label><input type="radio" name="num" value="3" /> 3</label></li> |
|
597 </ul> |
|
598 |
|
599 If 'choices' is passed to both the constructor and render(), then they'll both be in the output: |
|
600 >>> print w.render('num', 2, choices=[(4, 4), (5, 5)]) |
|
601 <ul> |
|
602 <li><label><input type="radio" name="num" value="1" /> 1</label></li> |
|
603 <li><label><input checked="checked" type="radio" name="num" value="2" /> 2</label></li> |
|
604 <li><label><input type="radio" name="num" value="3" /> 3</label></li> |
|
605 <li><label><input type="radio" name="num" value="4" /> 4</label></li> |
|
606 <li><label><input type="radio" name="num" value="5" /> 5</label></li> |
|
607 </ul> |
|
608 |
|
609 The render() method returns a RadioFieldRenderer object, whose str() is a <ul>. |
|
610 You can manipulate that object directly to customize the way the RadioSelect |
|
611 is rendered. |
|
612 >>> w = RadioSelect() |
|
613 >>> r = w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
614 >>> for inp in r: |
|
615 ... print inp |
|
616 <label><input checked="checked" type="radio" name="beatle" value="J" /> John</label> |
|
617 <label><input type="radio" name="beatle" value="P" /> Paul</label> |
|
618 <label><input type="radio" name="beatle" value="G" /> George</label> |
|
619 <label><input type="radio" name="beatle" value="R" /> Ringo</label> |
|
620 >>> for inp in r: |
|
621 ... print '%s<br />' % inp |
|
622 <label><input checked="checked" type="radio" name="beatle" value="J" /> John</label><br /> |
|
623 <label><input type="radio" name="beatle" value="P" /> Paul</label><br /> |
|
624 <label><input type="radio" name="beatle" value="G" /> George</label><br /> |
|
625 <label><input type="radio" name="beatle" value="R" /> Ringo</label><br /> |
|
626 >>> for inp in r: |
|
627 ... print '<p>%s %s</p>' % (inp.tag(), inp.choice_label) |
|
628 <p><input checked="checked" type="radio" name="beatle" value="J" /> John</p> |
|
629 <p><input type="radio" name="beatle" value="P" /> Paul</p> |
|
630 <p><input type="radio" name="beatle" value="G" /> George</p> |
|
631 <p><input type="radio" name="beatle" value="R" /> Ringo</p> |
|
632 >>> for inp in r: |
|
633 ... print '%s %s %s %s %s' % (inp.name, inp.value, inp.choice_value, inp.choice_label, inp.is_checked()) |
|
634 beatle J J John True |
|
635 beatle J P Paul False |
|
636 beatle J G George False |
|
637 beatle J R Ringo False |
|
638 |
|
639 A RadioFieldRenderer object also allows index access to individual RadioInput |
|
640 objects. |
|
641 >>> w = RadioSelect() |
|
642 >>> r = w.render('beatle', 'J', choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
643 >>> print r[1] |
|
644 <label><input type="radio" name="beatle" value="P" /> Paul</label> |
|
645 >>> print r[0] |
|
646 <label><input checked="checked" type="radio" name="beatle" value="J" /> John</label> |
|
647 >>> r[0].is_checked() |
|
648 True |
|
649 >>> r[1].is_checked() |
|
650 False |
|
651 >>> r[1].name, r[1].value, r[1].choice_value, r[1].choice_label |
|
652 ('beatle', u'J', u'P', u'Paul') |
|
653 >>> r[10] |
|
654 Traceback (most recent call last): |
|
655 ... |
|
656 IndexError: list index out of range |
|
657 |
|
658 >>> w = RadioSelect() |
|
659 >>> unicode(w.render('email', 'ŠĐĆŽćžšđ', choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')])) |
|
660 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>' |
|
661 |
|
662 # CheckboxSelectMultiple Widget ############################################### |
|
663 |
|
664 >>> w = CheckboxSelectMultiple() |
|
665 >>> print w.render('beatles', ['J'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
666 <ul> |
|
667 <li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> |
|
668 <li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> |
|
669 <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> |
|
670 <li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> |
|
671 </ul> |
|
672 >>> print w.render('beatles', ['J', 'P'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
673 <ul> |
|
674 <li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> |
|
675 <li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li> |
|
676 <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> |
|
677 <li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> |
|
678 </ul> |
|
679 >>> print w.render('beatles', ['J', 'P', 'R'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
680 <ul> |
|
681 <li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> |
|
682 <li><label><input checked="checked" type="checkbox" name="beatles" value="P" /> Paul</label></li> |
|
683 <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> |
|
684 <li><label><input checked="checked" type="checkbox" name="beatles" value="R" /> Ringo</label></li> |
|
685 </ul> |
|
686 |
|
687 If the value is None, none of the options are selected: |
|
688 >>> print w.render('beatles', None, choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
689 <ul> |
|
690 <li><label><input type="checkbox" name="beatles" value="J" /> John</label></li> |
|
691 <li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> |
|
692 <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> |
|
693 <li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> |
|
694 </ul> |
|
695 |
|
696 If the value corresponds to a label (but not to an option value), none of the options are selected: |
|
697 >>> print w.render('beatles', ['John'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
698 <ul> |
|
699 <li><label><input type="checkbox" name="beatles" value="J" /> John</label></li> |
|
700 <li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> |
|
701 <li><label><input type="checkbox" name="beatles" value="G" /> George</label></li> |
|
702 <li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> |
|
703 </ul> |
|
704 |
|
705 If multiple values are given, but some of them are not valid, the valid ones are selected: |
|
706 >>> print w.render('beatles', ['J', 'G', 'foo'], choices=(('J', 'John'), ('P', 'Paul'), ('G', 'George'), ('R', 'Ringo'))) |
|
707 <ul> |
|
708 <li><label><input checked="checked" type="checkbox" name="beatles" value="J" /> John</label></li> |
|
709 <li><label><input type="checkbox" name="beatles" value="P" /> Paul</label></li> |
|
710 <li><label><input checked="checked" type="checkbox" name="beatles" value="G" /> George</label></li> |
|
711 <li><label><input type="checkbox" name="beatles" value="R" /> Ringo</label></li> |
|
712 </ul> |
|
713 |
|
714 The value is compared to its str(): |
|
715 >>> print w.render('nums', [2], choices=[('1', '1'), ('2', '2'), ('3', '3')]) |
|
716 <ul> |
|
717 <li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> |
|
718 <li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> |
|
719 <li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> |
|
720 </ul> |
|
721 >>> print w.render('nums', ['2'], choices=[(1, 1), (2, 2), (3, 3)]) |
|
722 <ul> |
|
723 <li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> |
|
724 <li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> |
|
725 <li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> |
|
726 </ul> |
|
727 >>> print w.render('nums', [2], choices=[(1, 1), (2, 2), (3, 3)]) |
|
728 <ul> |
|
729 <li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> |
|
730 <li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> |
|
731 <li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> |
|
732 </ul> |
|
733 |
|
734 The 'choices' argument can be any iterable: |
|
735 >>> def get_choices(): |
|
736 ... for i in range(5): |
|
737 ... yield (i, i) |
|
738 >>> print w.render('nums', [2], choices=get_choices()) |
|
739 <ul> |
|
740 <li><label><input type="checkbox" name="nums" value="0" /> 0</label></li> |
|
741 <li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> |
|
742 <li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> |
|
743 <li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> |
|
744 <li><label><input type="checkbox" name="nums" value="4" /> 4</label></li> |
|
745 </ul> |
|
746 |
|
747 You can also pass 'choices' to the constructor: |
|
748 >>> w = CheckboxSelectMultiple(choices=[(1, 1), (2, 2), (3, 3)]) |
|
749 >>> print w.render('nums', [2]) |
|
750 <ul> |
|
751 <li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> |
|
752 <li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> |
|
753 <li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> |
|
754 </ul> |
|
755 |
|
756 If 'choices' is passed to both the constructor and render(), then they'll both be in the output: |
|
757 >>> print w.render('nums', [2], choices=[(4, 4), (5, 5)]) |
|
758 <ul> |
|
759 <li><label><input type="checkbox" name="nums" value="1" /> 1</label></li> |
|
760 <li><label><input checked="checked" type="checkbox" name="nums" value="2" /> 2</label></li> |
|
761 <li><label><input type="checkbox" name="nums" value="3" /> 3</label></li> |
|
762 <li><label><input type="checkbox" name="nums" value="4" /> 4</label></li> |
|
763 <li><label><input type="checkbox" name="nums" value="5" /> 5</label></li> |
|
764 </ul> |
|
765 |
|
766 >>> w.render('nums', ['ŠĐĆŽćžšđ'], choices=[('ŠĐĆŽćžšđ', 'ŠĐabcĆŽćžšđ'), ('ćžšđ', 'abcćžšđ')]) |
|
767 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>' |
|
768 |
|
769 # MultiWidget ################################################################# |
|
770 |
|
771 >>> class MyMultiWidget(MultiWidget): |
|
772 ... def decompress(self, value): |
|
773 ... if value: |
|
774 ... return value.split('__') |
|
775 ... return ['', ''] |
|
776 ... def format_output(self, rendered_widgets): |
|
777 ... return u'<br />'.join(rendered_widgets) |
|
778 >>> w = MyMultiWidget(widgets=(TextInput(attrs={'class': 'big'}), TextInput(attrs={'class': 'small'}))) |
|
779 >>> w.render('name', ['john', 'lennon']) |
|
780 u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />' |
|
781 >>> w.render('name', 'john__lennon') |
|
782 u'<input type="text" class="big" value="john" name="name_0" /><br /><input type="text" class="small" value="lennon" name="name_1" />' |
|
783 |
|
784 # SplitDateTimeWidget ######################################################### |
|
785 |
|
786 >>> w = SplitDateTimeWidget() |
|
787 >>> w.render('date', '') |
|
788 u'<input type="text" name="date_0" /><input type="text" name="date_1" />' |
|
789 >>> w.render('date', None) |
|
790 u'<input type="text" name="date_0" /><input type="text" name="date_1" />' |
|
791 >>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30)) |
|
792 u'<input type="text" name="date_0" value="2006-01-10" /><input type="text" name="date_1" value="07:30:00" />' |
|
793 >>> w.render('date', [datetime.date(2006, 1, 10), datetime.time(7, 30)]) |
|
794 u'<input type="text" name="date_0" value="2006-01-10" /><input type="text" name="date_1" value="07:30:00" />' |
|
795 |
|
796 You can also pass 'attrs' to the constructor. In this case, the attrs will be |
|
797 included on both widgets. |
|
798 >>> w = SplitDateTimeWidget(attrs={'class': 'pretty'}) |
|
799 >>> w.render('date', datetime.datetime(2006, 1, 10, 7, 30)) |
|
800 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" />' |
|
801 |
|
802 ########## |
|
803 # Fields # |
|
804 ########## |
|
805 |
|
806 Each Field class does some sort of validation. Each Field has a clean() method, |
|
807 which either raises django.newforms.ValidationError or returns the "clean" |
|
808 data -- usually a Unicode object, but, in some rare cases, a list. |
|
809 |
|
810 Each Field's __init__() takes at least these parameters: |
|
811 required -- Boolean that specifies whether the field is required. |
|
812 True by default. |
|
813 widget -- A Widget class, or instance of a Widget class, that should be |
|
814 used for this Field when displaying it. Each Field has a default |
|
815 Widget that it'll use if you don't specify this. In most cases, |
|
816 the default widget is TextInput. |
|
817 label -- A verbose name for this field, for use in displaying this field in |
|
818 a form. By default, Django will use a "pretty" version of the form |
|
819 field name, if the Field is part of a Form. |
|
820 initial -- A value to use in this Field's initial display. This value is |
|
821 *not* used as a fallback if data isn't given. |
|
822 |
|
823 Other than that, the Field subclasses have class-specific options for |
|
824 __init__(). For example, CharField has a max_length option. |
|
825 |
|
826 # CharField ################################################################### |
|
827 |
|
828 >>> f = CharField() |
|
829 >>> f.clean(1) |
|
830 u'1' |
|
831 >>> f.clean('hello') |
|
832 u'hello' |
|
833 >>> f.clean(None) |
|
834 Traceback (most recent call last): |
|
835 ... |
|
836 ValidationError: [u'This field is required.'] |
|
837 >>> f.clean('') |
|
838 Traceback (most recent call last): |
|
839 ... |
|
840 ValidationError: [u'This field is required.'] |
|
841 >>> f.clean([1, 2, 3]) |
|
842 u'[1, 2, 3]' |
|
843 |
|
844 >>> f = CharField(required=False) |
|
845 >>> f.clean(1) |
|
846 u'1' |
|
847 >>> f.clean('hello') |
|
848 u'hello' |
|
849 >>> f.clean(None) |
|
850 u'' |
|
851 >>> f.clean('') |
|
852 u'' |
|
853 >>> f.clean([1, 2, 3]) |
|
854 u'[1, 2, 3]' |
|
855 |
|
856 CharField accepts an optional max_length parameter: |
|
857 >>> f = CharField(max_length=10, required=False) |
|
858 >>> f.clean('12345') |
|
859 u'12345' |
|
860 >>> f.clean('1234567890') |
|
861 u'1234567890' |
|
862 >>> f.clean('1234567890a') |
|
863 Traceback (most recent call last): |
|
864 ... |
|
865 ValidationError: [u'Ensure this value has at most 10 characters.'] |
|
866 |
|
867 CharField accepts an optional min_length parameter: |
|
868 >>> f = CharField(min_length=10, required=False) |
|
869 >>> f.clean('') |
|
870 u'' |
|
871 >>> f.clean('12345') |
|
872 Traceback (most recent call last): |
|
873 ... |
|
874 ValidationError: [u'Ensure this value has at least 10 characters.'] |
|
875 >>> f.clean('1234567890') |
|
876 u'1234567890' |
|
877 >>> f.clean('1234567890a') |
|
878 u'1234567890a' |
|
879 |
|
880 >>> f = CharField(min_length=10, required=True) |
|
881 >>> f.clean('') |
|
882 Traceback (most recent call last): |
|
883 ... |
|
884 ValidationError: [u'This field is required.'] |
|
885 >>> f.clean('12345') |
|
886 Traceback (most recent call last): |
|
887 ... |
|
888 ValidationError: [u'Ensure this value has at least 10 characters.'] |
|
889 >>> f.clean('1234567890') |
|
890 u'1234567890' |
|
891 >>> f.clean('1234567890a') |
|
892 u'1234567890a' |
|
893 |
|
894 # IntegerField ################################################################ |
|
895 |
|
896 >>> f = IntegerField() |
|
897 >>> f.clean('') |
|
898 Traceback (most recent call last): |
|
899 ... |
|
900 ValidationError: [u'This field is required.'] |
|
901 >>> f.clean(None) |
|
902 Traceback (most recent call last): |
|
903 ... |
|
904 ValidationError: [u'This field is required.'] |
|
905 >>> f.clean('1') |
|
906 1 |
|
907 >>> isinstance(f.clean('1'), int) |
|
908 True |
|
909 >>> f.clean('23') |
|
910 23 |
|
911 >>> f.clean('a') |
|
912 Traceback (most recent call last): |
|
913 ... |
|
914 ValidationError: [u'Enter a whole number.'] |
|
915 >>> f.clean('1 ') |
|
916 1 |
|
917 >>> f.clean(' 1') |
|
918 1 |
|
919 >>> f.clean(' 1 ') |
|
920 1 |
|
921 >>> f.clean('1a') |
|
922 Traceback (most recent call last): |
|
923 ... |
|
924 ValidationError: [u'Enter a whole number.'] |
|
925 |
|
926 >>> f = IntegerField(required=False) |
|
927 >>> f.clean('') |
|
928 >>> repr(f.clean('')) |
|
929 'None' |
|
930 >>> f.clean(None) |
|
931 >>> repr(f.clean(None)) |
|
932 'None' |
|
933 >>> f.clean('1') |
|
934 1 |
|
935 >>> isinstance(f.clean('1'), int) |
|
936 True |
|
937 >>> f.clean('23') |
|
938 23 |
|
939 >>> f.clean('a') |
|
940 Traceback (most recent call last): |
|
941 ... |
|
942 ValidationError: [u'Enter a whole number.'] |
|
943 >>> f.clean('1 ') |
|
944 1 |
|
945 >>> f.clean(' 1') |
|
946 1 |
|
947 >>> f.clean(' 1 ') |
|
948 1 |
|
949 >>> f.clean('1a') |
|
950 Traceback (most recent call last): |
|
951 ... |
|
952 ValidationError: [u'Enter a whole number.'] |
|
953 |
|
954 IntegerField accepts an optional max_value parameter: |
|
955 >>> f = IntegerField(max_value=10) |
|
956 >>> f.clean(None) |
|
957 Traceback (most recent call last): |
|
958 ... |
|
959 ValidationError: [u'This field is required.'] |
|
960 >>> f.clean(1) |
|
961 1 |
|
962 >>> f.clean(10) |
|
963 10 |
|
964 >>> f.clean(11) |
|
965 Traceback (most recent call last): |
|
966 ... |
|
967 ValidationError: [u'Ensure this value is less than or equal to 10.'] |
|
968 >>> f.clean('10') |
|
969 10 |
|
970 >>> f.clean('11') |
|
971 Traceback (most recent call last): |
|
972 ... |
|
973 ValidationError: [u'Ensure this value is less than or equal to 10.'] |
|
974 |
|
975 IntegerField accepts an optional min_value parameter: |
|
976 >>> f = IntegerField(min_value=10) |
|
977 >>> f.clean(None) |
|
978 Traceback (most recent call last): |
|
979 ... |
|
980 ValidationError: [u'This field is required.'] |
|
981 >>> f.clean(1) |
|
982 Traceback (most recent call last): |
|
983 ... |
|
984 ValidationError: [u'Ensure this value is greater than or equal to 10.'] |
|
985 >>> f.clean(10) |
|
986 10 |
|
987 >>> f.clean(11) |
|
988 11 |
|
989 >>> f.clean('10') |
|
990 10 |
|
991 >>> f.clean('11') |
|
992 11 |
|
993 |
|
994 min_value and max_value can be used together: |
|
995 >>> f = IntegerField(min_value=10, max_value=20) |
|
996 >>> f.clean(None) |
|
997 Traceback (most recent call last): |
|
998 ... |
|
999 ValidationError: [u'This field is required.'] |
|
1000 >>> f.clean(1) |
|
1001 Traceback (most recent call last): |
|
1002 ... |
|
1003 ValidationError: [u'Ensure this value is greater than or equal to 10.'] |
|
1004 >>> f.clean(10) |
|
1005 10 |
|
1006 >>> f.clean(11) |
|
1007 11 |
|
1008 >>> f.clean('10') |
|
1009 10 |
|
1010 >>> f.clean('11') |
|
1011 11 |
|
1012 >>> f.clean(20) |
|
1013 20 |
|
1014 >>> f.clean(21) |
|
1015 Traceback (most recent call last): |
|
1016 ... |
|
1017 ValidationError: [u'Ensure this value is less than or equal to 20.'] |
|
1018 |
|
1019 # DateField ################################################################### |
|
1020 |
|
1021 >>> import datetime |
|
1022 >>> f = DateField() |
|
1023 >>> f.clean(datetime.date(2006, 10, 25)) |
|
1024 datetime.date(2006, 10, 25) |
|
1025 >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) |
|
1026 datetime.date(2006, 10, 25) |
|
1027 >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) |
|
1028 datetime.date(2006, 10, 25) |
|
1029 >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) |
|
1030 datetime.date(2006, 10, 25) |
|
1031 >>> f.clean('2006-10-25') |
|
1032 datetime.date(2006, 10, 25) |
|
1033 >>> f.clean('10/25/2006') |
|
1034 datetime.date(2006, 10, 25) |
|
1035 >>> f.clean('10/25/06') |
|
1036 datetime.date(2006, 10, 25) |
|
1037 >>> f.clean('Oct 25 2006') |
|
1038 datetime.date(2006, 10, 25) |
|
1039 >>> f.clean('October 25 2006') |
|
1040 datetime.date(2006, 10, 25) |
|
1041 >>> f.clean('October 25, 2006') |
|
1042 datetime.date(2006, 10, 25) |
|
1043 >>> f.clean('25 October 2006') |
|
1044 datetime.date(2006, 10, 25) |
|
1045 >>> f.clean('25 October, 2006') |
|
1046 datetime.date(2006, 10, 25) |
|
1047 >>> f.clean('2006-4-31') |
|
1048 Traceback (most recent call last): |
|
1049 ... |
|
1050 ValidationError: [u'Enter a valid date.'] |
|
1051 >>> f.clean('200a-10-25') |
|
1052 Traceback (most recent call last): |
|
1053 ... |
|
1054 ValidationError: [u'Enter a valid date.'] |
|
1055 >>> f.clean('25/10/06') |
|
1056 Traceback (most recent call last): |
|
1057 ... |
|
1058 ValidationError: [u'Enter a valid date.'] |
|
1059 >>> f.clean(None) |
|
1060 Traceback (most recent call last): |
|
1061 ... |
|
1062 ValidationError: [u'This field is required.'] |
|
1063 |
|
1064 >>> f = DateField(required=False) |
|
1065 >>> f.clean(None) |
|
1066 >>> repr(f.clean(None)) |
|
1067 'None' |
|
1068 >>> f.clean('') |
|
1069 >>> repr(f.clean('')) |
|
1070 'None' |
|
1071 |
|
1072 DateField accepts an optional input_formats parameter: |
|
1073 >>> f = DateField(input_formats=['%Y %m %d']) |
|
1074 >>> f.clean(datetime.date(2006, 10, 25)) |
|
1075 datetime.date(2006, 10, 25) |
|
1076 >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) |
|
1077 datetime.date(2006, 10, 25) |
|
1078 >>> f.clean('2006 10 25') |
|
1079 datetime.date(2006, 10, 25) |
|
1080 |
|
1081 The input_formats parameter overrides all default input formats, |
|
1082 so the default formats won't work unless you specify them: |
|
1083 >>> f.clean('2006-10-25') |
|
1084 Traceback (most recent call last): |
|
1085 ... |
|
1086 ValidationError: [u'Enter a valid date.'] |
|
1087 >>> f.clean('10/25/2006') |
|
1088 Traceback (most recent call last): |
|
1089 ... |
|
1090 ValidationError: [u'Enter a valid date.'] |
|
1091 >>> f.clean('10/25/06') |
|
1092 Traceback (most recent call last): |
|
1093 ... |
|
1094 ValidationError: [u'Enter a valid date.'] |
|
1095 |
|
1096 # TimeField ################################################################### |
|
1097 |
|
1098 >>> import datetime |
|
1099 >>> f = TimeField() |
|
1100 >>> f.clean(datetime.time(14, 25)) |
|
1101 datetime.time(14, 25) |
|
1102 >>> f.clean(datetime.time(14, 25, 59)) |
|
1103 datetime.time(14, 25, 59) |
|
1104 >>> f.clean('14:25') |
|
1105 datetime.time(14, 25) |
|
1106 >>> f.clean('14:25:59') |
|
1107 datetime.time(14, 25, 59) |
|
1108 >>> f.clean('hello') |
|
1109 Traceback (most recent call last): |
|
1110 ... |
|
1111 ValidationError: [u'Enter a valid time.'] |
|
1112 >>> f.clean('1:24 p.m.') |
|
1113 Traceback (most recent call last): |
|
1114 ... |
|
1115 ValidationError: [u'Enter a valid time.'] |
|
1116 |
|
1117 TimeField accepts an optional input_formats parameter: |
|
1118 >>> f = TimeField(input_formats=['%I:%M %p']) |
|
1119 >>> f.clean(datetime.time(14, 25)) |
|
1120 datetime.time(14, 25) |
|
1121 >>> f.clean(datetime.time(14, 25, 59)) |
|
1122 datetime.time(14, 25, 59) |
|
1123 >>> f.clean('4:25 AM') |
|
1124 datetime.time(4, 25) |
|
1125 >>> f.clean('4:25 PM') |
|
1126 datetime.time(16, 25) |
|
1127 |
|
1128 The input_formats parameter overrides all default input formats, |
|
1129 so the default formats won't work unless you specify them: |
|
1130 >>> f.clean('14:30:45') |
|
1131 Traceback (most recent call last): |
|
1132 ... |
|
1133 ValidationError: [u'Enter a valid time.'] |
|
1134 |
|
1135 # DateTimeField ############################################################### |
|
1136 |
|
1137 >>> import datetime |
|
1138 >>> f = DateTimeField() |
|
1139 >>> f.clean(datetime.date(2006, 10, 25)) |
|
1140 datetime.datetime(2006, 10, 25, 0, 0) |
|
1141 >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) |
|
1142 datetime.datetime(2006, 10, 25, 14, 30) |
|
1143 >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) |
|
1144 datetime.datetime(2006, 10, 25, 14, 30, 59) |
|
1145 >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) |
|
1146 datetime.datetime(2006, 10, 25, 14, 30, 59, 200) |
|
1147 >>> f.clean('2006-10-25 14:30:45') |
|
1148 datetime.datetime(2006, 10, 25, 14, 30, 45) |
|
1149 >>> f.clean('2006-10-25 14:30:00') |
|
1150 datetime.datetime(2006, 10, 25, 14, 30) |
|
1151 >>> f.clean('2006-10-25 14:30') |
|
1152 datetime.datetime(2006, 10, 25, 14, 30) |
|
1153 >>> f.clean('2006-10-25') |
|
1154 datetime.datetime(2006, 10, 25, 0, 0) |
|
1155 >>> f.clean('10/25/2006 14:30:45') |
|
1156 datetime.datetime(2006, 10, 25, 14, 30, 45) |
|
1157 >>> f.clean('10/25/2006 14:30:00') |
|
1158 datetime.datetime(2006, 10, 25, 14, 30) |
|
1159 >>> f.clean('10/25/2006 14:30') |
|
1160 datetime.datetime(2006, 10, 25, 14, 30) |
|
1161 >>> f.clean('10/25/2006') |
|
1162 datetime.datetime(2006, 10, 25, 0, 0) |
|
1163 >>> f.clean('10/25/06 14:30:45') |
|
1164 datetime.datetime(2006, 10, 25, 14, 30, 45) |
|
1165 >>> f.clean('10/25/06 14:30:00') |
|
1166 datetime.datetime(2006, 10, 25, 14, 30) |
|
1167 >>> f.clean('10/25/06 14:30') |
|
1168 datetime.datetime(2006, 10, 25, 14, 30) |
|
1169 >>> f.clean('10/25/06') |
|
1170 datetime.datetime(2006, 10, 25, 0, 0) |
|
1171 >>> f.clean('hello') |
|
1172 Traceback (most recent call last): |
|
1173 ... |
|
1174 ValidationError: [u'Enter a valid date/time.'] |
|
1175 >>> f.clean('2006-10-25 4:30 p.m.') |
|
1176 Traceback (most recent call last): |
|
1177 ... |
|
1178 ValidationError: [u'Enter a valid date/time.'] |
|
1179 |
|
1180 DateField accepts an optional input_formats parameter: |
|
1181 >>> f = DateTimeField(input_formats=['%Y %m %d %I:%M %p']) |
|
1182 >>> f.clean(datetime.date(2006, 10, 25)) |
|
1183 datetime.datetime(2006, 10, 25, 0, 0) |
|
1184 >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30)) |
|
1185 datetime.datetime(2006, 10, 25, 14, 30) |
|
1186 >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59)) |
|
1187 datetime.datetime(2006, 10, 25, 14, 30, 59) |
|
1188 >>> f.clean(datetime.datetime(2006, 10, 25, 14, 30, 59, 200)) |
|
1189 datetime.datetime(2006, 10, 25, 14, 30, 59, 200) |
|
1190 >>> f.clean('2006 10 25 2:30 PM') |
|
1191 datetime.datetime(2006, 10, 25, 14, 30) |
|
1192 |
|
1193 The input_formats parameter overrides all default input formats, |
|
1194 so the default formats won't work unless you specify them: |
|
1195 >>> f.clean('2006-10-25 14:30:45') |
|
1196 Traceback (most recent call last): |
|
1197 ... |
|
1198 ValidationError: [u'Enter a valid date/time.'] |
|
1199 |
|
1200 >>> f = DateTimeField(required=False) |
|
1201 >>> f.clean(None) |
|
1202 >>> repr(f.clean(None)) |
|
1203 'None' |
|
1204 >>> f.clean('') |
|
1205 >>> repr(f.clean('')) |
|
1206 'None' |
|
1207 |
|
1208 # RegexField ################################################################## |
|
1209 |
|
1210 >>> f = RegexField('^\d[A-F]\d$') |
|
1211 >>> f.clean('2A2') |
|
1212 u'2A2' |
|
1213 >>> f.clean('3F3') |
|
1214 u'3F3' |
|
1215 >>> f.clean('3G3') |
|
1216 Traceback (most recent call last): |
|
1217 ... |
|
1218 ValidationError: [u'Enter a valid value.'] |
|
1219 >>> f.clean(' 2A2') |
|
1220 Traceback (most recent call last): |
|
1221 ... |
|
1222 ValidationError: [u'Enter a valid value.'] |
|
1223 >>> f.clean('2A2 ') |
|
1224 Traceback (most recent call last): |
|
1225 ... |
|
1226 ValidationError: [u'Enter a valid value.'] |
|
1227 >>> f.clean('') |
|
1228 Traceback (most recent call last): |
|
1229 ... |
|
1230 ValidationError: [u'This field is required.'] |
|
1231 |
|
1232 >>> f = RegexField('^\d[A-F]\d$', required=False) |
|
1233 >>> f.clean('2A2') |
|
1234 u'2A2' |
|
1235 >>> f.clean('3F3') |
|
1236 u'3F3' |
|
1237 >>> f.clean('3G3') |
|
1238 Traceback (most recent call last): |
|
1239 ... |
|
1240 ValidationError: [u'Enter a valid value.'] |
|
1241 >>> f.clean('') |
|
1242 u'' |
|
1243 |
|
1244 Alternatively, RegexField can take a compiled regular expression: |
|
1245 >>> f = RegexField(re.compile('^\d[A-F]\d$')) |
|
1246 >>> f.clean('2A2') |
|
1247 u'2A2' |
|
1248 >>> f.clean('3F3') |
|
1249 u'3F3' |
|
1250 >>> f.clean('3G3') |
|
1251 Traceback (most recent call last): |
|
1252 ... |
|
1253 ValidationError: [u'Enter a valid value.'] |
|
1254 >>> f.clean(' 2A2') |
|
1255 Traceback (most recent call last): |
|
1256 ... |
|
1257 ValidationError: [u'Enter a valid value.'] |
|
1258 >>> f.clean('2A2 ') |
|
1259 Traceback (most recent call last): |
|
1260 ... |
|
1261 ValidationError: [u'Enter a valid value.'] |
|
1262 |
|
1263 RegexField takes an optional error_message argument: |
|
1264 >>> f = RegexField('^\d\d\d\d$', error_message='Enter a four-digit number.') |
|
1265 >>> f.clean('1234') |
|
1266 u'1234' |
|
1267 >>> f.clean('123') |
|
1268 Traceback (most recent call last): |
|
1269 ... |
|
1270 ValidationError: [u'Enter a four-digit number.'] |
|
1271 >>> f.clean('abcd') |
|
1272 Traceback (most recent call last): |
|
1273 ... |
|
1274 ValidationError: [u'Enter a four-digit number.'] |
|
1275 |
|
1276 RegexField also access min_length and max_length parameters, for convenience. |
|
1277 >>> f = RegexField('^\d+$', min_length=5, max_length=10) |
|
1278 >>> f.clean('123') |
|
1279 Traceback (most recent call last): |
|
1280 ... |
|
1281 ValidationError: [u'Ensure this value has at least 5 characters.'] |
|
1282 >>> f.clean('abc') |
|
1283 Traceback (most recent call last): |
|
1284 ... |
|
1285 ValidationError: [u'Ensure this value has at least 5 characters.'] |
|
1286 >>> f.clean('12345') |
|
1287 u'12345' |
|
1288 >>> f.clean('1234567890') |
|
1289 u'1234567890' |
|
1290 >>> f.clean('12345678901') |
|
1291 Traceback (most recent call last): |
|
1292 ... |
|
1293 ValidationError: [u'Ensure this value has at most 10 characters.'] |
|
1294 >>> f.clean('12345a') |
|
1295 Traceback (most recent call last): |
|
1296 ... |
|
1297 ValidationError: [u'Enter a valid value.'] |
|
1298 |
|
1299 # EmailField ################################################################## |
|
1300 |
|
1301 >>> f = EmailField() |
|
1302 >>> f.clean('') |
|
1303 Traceback (most recent call last): |
|
1304 ... |
|
1305 ValidationError: [u'This field is required.'] |
|
1306 >>> f.clean(None) |
|
1307 Traceback (most recent call last): |
|
1308 ... |
|
1309 ValidationError: [u'This field is required.'] |
|
1310 >>> f.clean('person@example.com') |
|
1311 u'person@example.com' |
|
1312 >>> f.clean('foo') |
|
1313 Traceback (most recent call last): |
|
1314 ... |
|
1315 ValidationError: [u'Enter a valid e-mail address.'] |
|
1316 >>> f.clean('foo@') |
|
1317 Traceback (most recent call last): |
|
1318 ... |
|
1319 ValidationError: [u'Enter a valid e-mail address.'] |
|
1320 >>> f.clean('foo@bar') |
|
1321 Traceback (most recent call last): |
|
1322 ... |
|
1323 ValidationError: [u'Enter a valid e-mail address.'] |
|
1324 |
|
1325 >>> f = EmailField(required=False) |
|
1326 >>> f.clean('') |
|
1327 u'' |
|
1328 >>> f.clean(None) |
|
1329 u'' |
|
1330 >>> f.clean('person@example.com') |
|
1331 u'person@example.com' |
|
1332 >>> f.clean('foo') |
|
1333 Traceback (most recent call last): |
|
1334 ... |
|
1335 ValidationError: [u'Enter a valid e-mail address.'] |
|
1336 >>> f.clean('foo@') |
|
1337 Traceback (most recent call last): |
|
1338 ... |
|
1339 ValidationError: [u'Enter a valid e-mail address.'] |
|
1340 >>> f.clean('foo@bar') |
|
1341 Traceback (most recent call last): |
|
1342 ... |
|
1343 ValidationError: [u'Enter a valid e-mail address.'] |
|
1344 |
|
1345 EmailField also access min_length and max_length parameters, for convenience. |
|
1346 >>> f = EmailField(min_length=10, max_length=15) |
|
1347 >>> f.clean('a@foo.com') |
|
1348 Traceback (most recent call last): |
|
1349 ... |
|
1350 ValidationError: [u'Ensure this value has at least 10 characters.'] |
|
1351 >>> f.clean('alf@foo.com') |
|
1352 u'alf@foo.com' |
|
1353 >>> f.clean('alf123456788@foo.com') |
|
1354 Traceback (most recent call last): |
|
1355 ... |
|
1356 ValidationError: [u'Ensure this value has at most 15 characters.'] |
|
1357 |
|
1358 # URLField ################################################################## |
|
1359 |
|
1360 >>> f = URLField() |
|
1361 >>> f.clean('') |
|
1362 Traceback (most recent call last): |
|
1363 ... |
|
1364 ValidationError: [u'This field is required.'] |
|
1365 >>> f.clean(None) |
|
1366 Traceback (most recent call last): |
|
1367 ... |
|
1368 ValidationError: [u'This field is required.'] |
|
1369 >>> f.clean('http://example.com') |
|
1370 u'http://example.com' |
|
1371 >>> f.clean('http://www.example.com') |
|
1372 u'http://www.example.com' |
|
1373 >>> f.clean('foo') |
|
1374 Traceback (most recent call last): |
|
1375 ... |
|
1376 ValidationError: [u'Enter a valid URL.'] |
|
1377 >>> f.clean('example.com') |
|
1378 Traceback (most recent call last): |
|
1379 ... |
|
1380 ValidationError: [u'Enter a valid URL.'] |
|
1381 >>> f.clean('http://') |
|
1382 Traceback (most recent call last): |
|
1383 ... |
|
1384 ValidationError: [u'Enter a valid URL.'] |
|
1385 >>> f.clean('http://example') |
|
1386 Traceback (most recent call last): |
|
1387 ... |
|
1388 ValidationError: [u'Enter a valid URL.'] |
|
1389 >>> f.clean('http://example.') |
|
1390 Traceback (most recent call last): |
|
1391 ... |
|
1392 ValidationError: [u'Enter a valid URL.'] |
|
1393 >>> f.clean('http://.com') |
|
1394 Traceback (most recent call last): |
|
1395 ... |
|
1396 ValidationError: [u'Enter a valid URL.'] |
|
1397 |
|
1398 >>> f = URLField(required=False) |
|
1399 >>> f.clean('') |
|
1400 u'' |
|
1401 >>> f.clean(None) |
|
1402 u'' |
|
1403 >>> f.clean('http://example.com') |
|
1404 u'http://example.com' |
|
1405 >>> f.clean('http://www.example.com') |
|
1406 u'http://www.example.com' |
|
1407 >>> f.clean('foo') |
|
1408 Traceback (most recent call last): |
|
1409 ... |
|
1410 ValidationError: [u'Enter a valid URL.'] |
|
1411 >>> f.clean('example.com') |
|
1412 Traceback (most recent call last): |
|
1413 ... |
|
1414 ValidationError: [u'Enter a valid URL.'] |
|
1415 >>> f.clean('http://') |
|
1416 Traceback (most recent call last): |
|
1417 ... |
|
1418 ValidationError: [u'Enter a valid URL.'] |
|
1419 >>> f.clean('http://example') |
|
1420 Traceback (most recent call last): |
|
1421 ... |
|
1422 ValidationError: [u'Enter a valid URL.'] |
|
1423 >>> f.clean('http://example.') |
|
1424 Traceback (most recent call last): |
|
1425 ... |
|
1426 ValidationError: [u'Enter a valid URL.'] |
|
1427 >>> f.clean('http://.com') |
|
1428 Traceback (most recent call last): |
|
1429 ... |
|
1430 ValidationError: [u'Enter a valid URL.'] |
|
1431 |
|
1432 URLField takes an optional verify_exists parameter, which is False by default. |
|
1433 This verifies that the URL is live on the Internet and doesn't return a 404 or 500: |
|
1434 >>> f = URLField(verify_exists=True) |
|
1435 >>> f.clean('http://www.google.com') # This will fail if there's no Internet connection |
|
1436 u'http://www.google.com' |
|
1437 >>> f.clean('http://example') |
|
1438 Traceback (most recent call last): |
|
1439 ... |
|
1440 ValidationError: [u'Enter a valid URL.'] |
|
1441 >>> f.clean('http://www.jfoiwjfoi23jfoijoaijfoiwjofiwjefewl.com') # bad domain |
|
1442 Traceback (most recent call last): |
|
1443 ... |
|
1444 ValidationError: [u'This URL appears to be a broken link.'] |
|
1445 >>> f.clean('http://google.com/we-love-microsoft.html') # good domain, bad page |
|
1446 Traceback (most recent call last): |
|
1447 ... |
|
1448 ValidationError: [u'This URL appears to be a broken link.'] |
|
1449 >>> f = URLField(verify_exists=True, required=False) |
|
1450 >>> f.clean('') |
|
1451 u'' |
|
1452 >>> f.clean('http://www.google.com') # This will fail if there's no Internet connection |
|
1453 u'http://www.google.com' |
|
1454 |
|
1455 EmailField also access min_length and max_length parameters, for convenience. |
|
1456 >>> f = URLField(min_length=15, max_length=20) |
|
1457 >>> f.clean('http://f.com') |
|
1458 Traceback (most recent call last): |
|
1459 ... |
|
1460 ValidationError: [u'Ensure this value has at least 15 characters.'] |
|
1461 >>> f.clean('http://example.com') |
|
1462 u'http://example.com' |
|
1463 >>> f.clean('http://abcdefghijklmnopqrstuvwxyz.com') |
|
1464 Traceback (most recent call last): |
|
1465 ... |
|
1466 ValidationError: [u'Ensure this value has at most 20 characters.'] |
|
1467 |
|
1468 # BooleanField ################################################################ |
|
1469 |
|
1470 >>> f = BooleanField() |
|
1471 >>> f.clean('') |
|
1472 Traceback (most recent call last): |
|
1473 ... |
|
1474 ValidationError: [u'This field is required.'] |
|
1475 >>> f.clean(None) |
|
1476 Traceback (most recent call last): |
|
1477 ... |
|
1478 ValidationError: [u'This field is required.'] |
|
1479 >>> f.clean(True) |
|
1480 True |
|
1481 >>> f.clean(False) |
|
1482 False |
|
1483 >>> f.clean(1) |
|
1484 True |
|
1485 >>> f.clean(0) |
|
1486 False |
|
1487 >>> f.clean('Django rocks') |
|
1488 True |
|
1489 |
|
1490 >>> f = BooleanField(required=False) |
|
1491 >>> f.clean('') |
|
1492 False |
|
1493 >>> f.clean(None) |
|
1494 False |
|
1495 >>> f.clean(True) |
|
1496 True |
|
1497 >>> f.clean(False) |
|
1498 False |
|
1499 >>> f.clean(1) |
|
1500 True |
|
1501 >>> f.clean(0) |
|
1502 False |
|
1503 >>> f.clean('Django rocks') |
|
1504 True |
|
1505 |
|
1506 # ChoiceField ################################################################# |
|
1507 |
|
1508 >>> f = ChoiceField(choices=[('1', '1'), ('2', '2')]) |
|
1509 >>> f.clean('') |
|
1510 Traceback (most recent call last): |
|
1511 ... |
|
1512 ValidationError: [u'This field is required.'] |
|
1513 >>> f.clean(None) |
|
1514 Traceback (most recent call last): |
|
1515 ... |
|
1516 ValidationError: [u'This field is required.'] |
|
1517 >>> f.clean(1) |
|
1518 u'1' |
|
1519 >>> f.clean('1') |
|
1520 u'1' |
|
1521 >>> f.clean('3') |
|
1522 Traceback (most recent call last): |
|
1523 ... |
|
1524 ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] |
|
1525 |
|
1526 >>> f = ChoiceField(choices=[('1', '1'), ('2', '2')], required=False) |
|
1527 >>> f.clean('') |
|
1528 u'' |
|
1529 >>> f.clean(None) |
|
1530 u'' |
|
1531 >>> f.clean(1) |
|
1532 u'1' |
|
1533 >>> f.clean('1') |
|
1534 u'1' |
|
1535 >>> f.clean('3') |
|
1536 Traceback (most recent call last): |
|
1537 ... |
|
1538 ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] |
|
1539 |
|
1540 >>> f = ChoiceField(choices=[('J', 'John'), ('P', 'Paul')]) |
|
1541 >>> f.clean('J') |
|
1542 u'J' |
|
1543 >>> f.clean('John') |
|
1544 Traceback (most recent call last): |
|
1545 ... |
|
1546 ValidationError: [u'Select a valid choice. That choice is not one of the available choices.'] |
|
1547 |
|
1548 # NullBooleanField ############################################################ |
|
1549 |
|
1550 >>> f = NullBooleanField() |
|
1551 >>> f.clean('') |
|
1552 >>> f.clean(True) |
|
1553 True |
|
1554 >>> f.clean(False) |
|
1555 False |
|
1556 >>> f.clean(None) |
|
1557 >>> f.clean('1') |
|
1558 >>> f.clean('2') |
|
1559 >>> f.clean('3') |
|
1560 >>> f.clean('hello') |
|
1561 |
|
1562 # MultipleChoiceField ######################################################### |
|
1563 |
|
1564 >>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')]) |
|
1565 >>> f.clean('') |
|
1566 Traceback (most recent call last): |
|
1567 ... |
|
1568 ValidationError: [u'This field is required.'] |
|
1569 >>> f.clean(None) |
|
1570 Traceback (most recent call last): |
|
1571 ... |
|
1572 ValidationError: [u'This field is required.'] |
|
1573 >>> f.clean([1]) |
|
1574 [u'1'] |
|
1575 >>> f.clean(['1']) |
|
1576 [u'1'] |
|
1577 >>> f.clean(['1', '2']) |
|
1578 [u'1', u'2'] |
|
1579 >>> f.clean([1, '2']) |
|
1580 [u'1', u'2'] |
|
1581 >>> f.clean((1, '2')) |
|
1582 [u'1', u'2'] |
|
1583 >>> f.clean('hello') |
|
1584 Traceback (most recent call last): |
|
1585 ... |
|
1586 ValidationError: [u'Enter a list of values.'] |
|
1587 >>> f.clean([]) |
|
1588 Traceback (most recent call last): |
|
1589 ... |
|
1590 ValidationError: [u'This field is required.'] |
|
1591 >>> f.clean(()) |
|
1592 Traceback (most recent call last): |
|
1593 ... |
|
1594 ValidationError: [u'This field is required.'] |
|
1595 >>> f.clean(['3']) |
|
1596 Traceback (most recent call last): |
|
1597 ... |
|
1598 ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] |
|
1599 |
|
1600 >>> f = MultipleChoiceField(choices=[('1', '1'), ('2', '2')], required=False) |
|
1601 >>> f.clean('') |
|
1602 [] |
|
1603 >>> f.clean(None) |
|
1604 [] |
|
1605 >>> f.clean([1]) |
|
1606 [u'1'] |
|
1607 >>> f.clean(['1']) |
|
1608 [u'1'] |
|
1609 >>> f.clean(['1', '2']) |
|
1610 [u'1', u'2'] |
|
1611 >>> f.clean([1, '2']) |
|
1612 [u'1', u'2'] |
|
1613 >>> f.clean((1, '2')) |
|
1614 [u'1', u'2'] |
|
1615 >>> f.clean('hello') |
|
1616 Traceback (most recent call last): |
|
1617 ... |
|
1618 ValidationError: [u'Enter a list of values.'] |
|
1619 >>> f.clean([]) |
|
1620 [] |
|
1621 >>> f.clean(()) |
|
1622 [] |
|
1623 >>> f.clean(['3']) |
|
1624 Traceback (most recent call last): |
|
1625 ... |
|
1626 ValidationError: [u'Select a valid choice. 3 is not one of the available choices.'] |
|
1627 |
|
1628 # ComboField ################################################################## |
|
1629 |
|
1630 ComboField takes a list of fields that should be used to validate a value, |
|
1631 in that order. |
|
1632 >>> f = ComboField(fields=[CharField(max_length=20), EmailField()]) |
|
1633 >>> f.clean('test@example.com') |
|
1634 u'test@example.com' |
|
1635 >>> f.clean('longemailaddress@example.com') |
|
1636 Traceback (most recent call last): |
|
1637 ... |
|
1638 ValidationError: [u'Ensure this value has at most 20 characters.'] |
|
1639 >>> f.clean('not an e-mail') |
|
1640 Traceback (most recent call last): |
|
1641 ... |
|
1642 ValidationError: [u'Enter a valid e-mail address.'] |
|
1643 >>> f.clean('') |
|
1644 Traceback (most recent call last): |
|
1645 ... |
|
1646 ValidationError: [u'This field is required.'] |
|
1647 >>> f.clean(None) |
|
1648 Traceback (most recent call last): |
|
1649 ... |
|
1650 ValidationError: [u'This field is required.'] |
|
1651 |
|
1652 >>> f = ComboField(fields=[CharField(max_length=20), EmailField()], required=False) |
|
1653 >>> f.clean('test@example.com') |
|
1654 u'test@example.com' |
|
1655 >>> f.clean('longemailaddress@example.com') |
|
1656 Traceback (most recent call last): |
|
1657 ... |
|
1658 ValidationError: [u'Ensure this value has at most 20 characters.'] |
|
1659 >>> f.clean('not an e-mail') |
|
1660 Traceback (most recent call last): |
|
1661 ... |
|
1662 ValidationError: [u'Enter a valid e-mail address.'] |
|
1663 >>> f.clean('') |
|
1664 u'' |
|
1665 >>> f.clean(None) |
|
1666 u'' |
|
1667 |
|
1668 # SplitDateTimeField ########################################################## |
|
1669 |
|
1670 >>> f = SplitDateTimeField() |
|
1671 >>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)]) |
|
1672 datetime.datetime(2006, 1, 10, 7, 30) |
|
1673 >>> f.clean(None) |
|
1674 Traceback (most recent call last): |
|
1675 ... |
|
1676 ValidationError: [u'This field is required.'] |
|
1677 >>> f.clean('') |
|
1678 Traceback (most recent call last): |
|
1679 ... |
|
1680 ValidationError: [u'This field is required.'] |
|
1681 >>> f.clean('hello') |
|
1682 Traceback (most recent call last): |
|
1683 ... |
|
1684 ValidationError: [u'Enter a list of values.'] |
|
1685 >>> f.clean(['hello', 'there']) |
|
1686 Traceback (most recent call last): |
|
1687 ... |
|
1688 ValidationError: [u'Enter a valid date.', u'Enter a valid time.'] |
|
1689 >>> f.clean(['2006-01-10', 'there']) |
|
1690 Traceback (most recent call last): |
|
1691 ... |
|
1692 ValidationError: [u'Enter a valid time.'] |
|
1693 >>> f.clean(['hello', '07:30']) |
|
1694 Traceback (most recent call last): |
|
1695 ... |
|
1696 ValidationError: [u'Enter a valid date.'] |
|
1697 |
|
1698 >>> f = SplitDateTimeField(required=False) |
|
1699 >>> f.clean([datetime.date(2006, 1, 10), datetime.time(7, 30)]) |
|
1700 datetime.datetime(2006, 1, 10, 7, 30) |
|
1701 >>> f.clean(None) |
|
1702 >>> f.clean('') |
|
1703 >>> f.clean('hello') |
|
1704 Traceback (most recent call last): |
|
1705 ... |
|
1706 ValidationError: [u'Enter a list of values.'] |
|
1707 >>> f.clean(['hello', 'there']) |
|
1708 Traceback (most recent call last): |
|
1709 ... |
|
1710 ValidationError: [u'Enter a valid date.', u'Enter a valid time.'] |
|
1711 >>> f.clean(['2006-01-10', 'there']) |
|
1712 Traceback (most recent call last): |
|
1713 ... |
|
1714 ValidationError: [u'Enter a valid time.'] |
|
1715 >>> f.clean(['hello', '07:30']) |
|
1716 Traceback (most recent call last): |
|
1717 ... |
|
1718 ValidationError: [u'Enter a valid date.'] |
|
1719 |
|
1720 ######### |
|
1721 # Forms # |
|
1722 ######### |
|
1723 |
|
1724 A Form is a collection of Fields. It knows how to validate a set of data and it |
|
1725 knows how to render itself in a couple of default ways (e.g., an HTML table). |
|
1726 You can pass it data in __init__(), as a dictionary. |
|
1727 |
|
1728 # Form ######################################################################## |
|
1729 |
|
1730 >>> class Person(Form): |
|
1731 ... first_name = CharField() |
|
1732 ... last_name = CharField() |
|
1733 ... birthday = DateField() |
|
1734 |
|
1735 Pass a dictionary to a Form's __init__(). |
|
1736 >>> p = Person({'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9'}) |
|
1737 >>> p.is_bound |
|
1738 True |
|
1739 >>> p.errors |
|
1740 {} |
|
1741 >>> p.is_valid() |
|
1742 True |
|
1743 >>> p.errors.as_ul() |
|
1744 u'' |
|
1745 >>> p.errors.as_text() |
|
1746 u'' |
|
1747 >>> p.clean_data |
|
1748 {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} |
|
1749 >>> print p['first_name'] |
|
1750 <input type="text" name="first_name" value="John" id="id_first_name" /> |
|
1751 >>> print p['last_name'] |
|
1752 <input type="text" name="last_name" value="Lennon" id="id_last_name" /> |
|
1753 >>> print p['birthday'] |
|
1754 <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /> |
|
1755 >>> print p['nonexistentfield'] |
|
1756 Traceback (most recent call last): |
|
1757 ... |
|
1758 KeyError: "Key 'nonexistentfield' not found in Form" |
|
1759 |
|
1760 >>> for boundfield in p: |
|
1761 ... print boundfield |
|
1762 <input type="text" name="first_name" value="John" id="id_first_name" /> |
|
1763 <input type="text" name="last_name" value="Lennon" id="id_last_name" /> |
|
1764 <input type="text" name="birthday" value="1940-10-9" id="id_birthday" /> |
|
1765 >>> for boundfield in p: |
|
1766 ... print boundfield.label, boundfield.data |
|
1767 First name John |
|
1768 Last name Lennon |
|
1769 Birthday 1940-10-9 |
|
1770 >>> print p |
|
1771 <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> |
|
1772 <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> |
|
1773 <tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" value="1940-10-9" id="id_birthday" /></td></tr> |
|
1774 |
|
1775 Empty dictionaries are valid, too. |
|
1776 >>> p = Person({}) |
|
1777 >>> p.is_bound |
|
1778 True |
|
1779 >>> p.errors |
|
1780 {'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} |
|
1781 >>> p.is_valid() |
|
1782 False |
|
1783 >>> p.clean_data |
|
1784 Traceback (most recent call last): |
|
1785 ... |
|
1786 AttributeError: 'Person' object has no attribute 'clean_data' |
|
1787 >>> print p |
|
1788 <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> |
|
1789 <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> |
|
1790 <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> |
|
1791 >>> print p.as_table() |
|
1792 <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> |
|
1793 <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> |
|
1794 <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> |
|
1795 >>> print p.as_ul() |
|
1796 <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> |
|
1797 <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> |
|
1798 <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> |
|
1799 >>> print p.as_p() |
|
1800 <p><ul class="errorlist"><li>This field is required.</li></ul></p> |
|
1801 <p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p> |
|
1802 <p><ul class="errorlist"><li>This field is required.</li></ul></p> |
|
1803 <p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p> |
|
1804 <p><ul class="errorlist"><li>This field is required.</li></ul></p> |
|
1805 <p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p> |
|
1806 |
|
1807 If you don't pass any values to the Form's __init__(), or if you pass None, |
|
1808 the Form will be considered unbound and won't do any validation. Form.errors |
|
1809 will be an empty dictionary *but* Form.is_valid() will return False. |
|
1810 >>> p = Person() |
|
1811 >>> p.is_bound |
|
1812 False |
|
1813 >>> p.errors |
|
1814 {} |
|
1815 >>> p.is_valid() |
|
1816 False |
|
1817 >>> p.clean_data |
|
1818 Traceback (most recent call last): |
|
1819 ... |
|
1820 AttributeError: 'Person' object has no attribute 'clean_data' |
|
1821 >>> print p |
|
1822 <tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> |
|
1823 <tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr> |
|
1824 <tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr> |
|
1825 >>> print p.as_table() |
|
1826 <tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> |
|
1827 <tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr> |
|
1828 <tr><th><label for="id_birthday">Birthday:</label></th><td><input type="text" name="birthday" id="id_birthday" /></td></tr> |
|
1829 >>> print p.as_ul() |
|
1830 <li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li> |
|
1831 <li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li> |
|
1832 <li><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></li> |
|
1833 >>> print p.as_p() |
|
1834 <p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p> |
|
1835 <p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p> |
|
1836 <p><label for="id_birthday">Birthday:</label> <input type="text" name="birthday" id="id_birthday" /></p> |
|
1837 |
|
1838 Unicode values are handled properly. |
|
1839 >>> p = Person({'first_name': u'John', 'last_name': u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111', 'birthday': '1940-10-9'}) |
|
1840 >>> p.as_table() |
|
1841 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>' |
|
1842 >>> p.as_ul() |
|
1843 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>' |
|
1844 >>> p.as_p() |
|
1845 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>' |
|
1846 |
|
1847 >>> p = Person({'last_name': u'Lennon'}) |
|
1848 >>> p.errors |
|
1849 {'first_name': [u'This field is required.'], 'birthday': [u'This field is required.']} |
|
1850 >>> p.is_valid() |
|
1851 False |
|
1852 >>> p.errors.as_ul() |
|
1853 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>' |
|
1854 >>> print p.errors.as_text() |
|
1855 * first_name |
|
1856 * This field is required. |
|
1857 * birthday |
|
1858 * This field is required. |
|
1859 >>> p.clean_data |
|
1860 Traceback (most recent call last): |
|
1861 ... |
|
1862 AttributeError: 'Person' object has no attribute 'clean_data' |
|
1863 >>> p['first_name'].errors |
|
1864 [u'This field is required.'] |
|
1865 >>> p['first_name'].errors.as_ul() |
|
1866 u'<ul class="errorlist"><li>This field is required.</li></ul>' |
|
1867 >>> p['first_name'].errors.as_text() |
|
1868 u'* This field is required.' |
|
1869 |
|
1870 >>> p = Person() |
|
1871 >>> print p['first_name'] |
|
1872 <input type="text" name="first_name" id="id_first_name" /> |
|
1873 >>> print p['last_name'] |
|
1874 <input type="text" name="last_name" id="id_last_name" /> |
|
1875 >>> print p['birthday'] |
|
1876 <input type="text" name="birthday" id="id_birthday" /> |
|
1877 |
|
1878 clean_data will always *only* contain a key for fields defined in the |
|
1879 Form, even if you pass extra data when you define the Form. In this |
|
1880 example, we pass a bunch of extra fields to the form constructor, |
|
1881 but clean_data contains only the form's fields. |
|
1882 >>> data = {'first_name': u'John', 'last_name': u'Lennon', 'birthday': u'1940-10-9', 'extra1': 'hello', 'extra2': 'hello'} |
|
1883 >>> p = Person(data) |
|
1884 >>> p.is_valid() |
|
1885 True |
|
1886 >>> p.clean_data |
|
1887 {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} |
|
1888 |
|
1889 "auto_id" tells the Form to add an "id" attribute to each form element. |
|
1890 If it's a string that contains '%s', Django will use that as a format string |
|
1891 into which the field's name will be inserted. It will also put a <label> around |
|
1892 the human-readable labels for a field. |
|
1893 >>> p = Person(auto_id='%s_id') |
|
1894 >>> print p.as_table() |
|
1895 <tr><th><label for="first_name_id">First name:</label></th><td><input type="text" name="first_name" id="first_name_id" /></td></tr> |
|
1896 <tr><th><label for="last_name_id">Last name:</label></th><td><input type="text" name="last_name" id="last_name_id" /></td></tr> |
|
1897 <tr><th><label for="birthday_id">Birthday:</label></th><td><input type="text" name="birthday" id="birthday_id" /></td></tr> |
|
1898 >>> print p.as_ul() |
|
1899 <li><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></li> |
|
1900 <li><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></li> |
|
1901 <li><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></li> |
|
1902 >>> print p.as_p() |
|
1903 <p><label for="first_name_id">First name:</label> <input type="text" name="first_name" id="first_name_id" /></p> |
|
1904 <p><label for="last_name_id">Last name:</label> <input type="text" name="last_name" id="last_name_id" /></p> |
|
1905 <p><label for="birthday_id">Birthday:</label> <input type="text" name="birthday" id="birthday_id" /></p> |
|
1906 |
|
1907 If auto_id is any True value whose str() does not contain '%s', the "id" |
|
1908 attribute will be the name of the field. |
|
1909 >>> p = Person(auto_id=True) |
|
1910 >>> print p.as_ul() |
|
1911 <li><label for="first_name">First name:</label> <input type="text" name="first_name" id="first_name" /></li> |
|
1912 <li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li> |
|
1913 <li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li> |
|
1914 |
|
1915 If auto_id is any False value, an "id" attribute won't be output unless it |
|
1916 was manually entered. |
|
1917 >>> p = Person(auto_id=False) |
|
1918 >>> print p.as_ul() |
|
1919 <li>First name: <input type="text" name="first_name" /></li> |
|
1920 <li>Last name: <input type="text" name="last_name" /></li> |
|
1921 <li>Birthday: <input type="text" name="birthday" /></li> |
|
1922 |
|
1923 In this example, auto_id is False, but the "id" attribute for the "first_name" |
|
1924 field is given. Also note that field gets a <label>, while the others don't. |
|
1925 >>> class PersonNew(Form): |
|
1926 ... first_name = CharField(widget=TextInput(attrs={'id': 'first_name_id'})) |
|
1927 ... last_name = CharField() |
|
1928 ... birthday = DateField() |
|
1929 >>> p = PersonNew(auto_id=False) |
|
1930 >>> print p.as_ul() |
|
1931 <li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li> |
|
1932 <li>Last name: <input type="text" name="last_name" /></li> |
|
1933 <li>Birthday: <input type="text" name="birthday" /></li> |
|
1934 |
|
1935 If the "id" attribute is specified in the Form and auto_id is True, the "id" |
|
1936 attribute in the Form gets precedence. |
|
1937 >>> p = PersonNew(auto_id=True) |
|
1938 >>> print p.as_ul() |
|
1939 <li><label for="first_name_id">First name:</label> <input type="text" id="first_name_id" name="first_name" /></li> |
|
1940 <li><label for="last_name">Last name:</label> <input type="text" name="last_name" id="last_name" /></li> |
|
1941 <li><label for="birthday">Birthday:</label> <input type="text" name="birthday" id="birthday" /></li> |
|
1942 |
|
1943 >>> class SignupForm(Form): |
|
1944 ... email = EmailField() |
|
1945 ... get_spam = BooleanField() |
|
1946 >>> f = SignupForm(auto_id=False) |
|
1947 >>> print f['email'] |
|
1948 <input type="text" name="email" /> |
|
1949 >>> print f['get_spam'] |
|
1950 <input type="checkbox" name="get_spam" /> |
|
1951 |
|
1952 >>> f = SignupForm({'email': 'test@example.com', 'get_spam': True}, auto_id=False) |
|
1953 >>> print f['email'] |
|
1954 <input type="text" name="email" value="test@example.com" /> |
|
1955 >>> print f['get_spam'] |
|
1956 <input checked="checked" type="checkbox" name="get_spam" /> |
|
1957 |
|
1958 Any Field can have a Widget class passed to its constructor: |
|
1959 >>> class ContactForm(Form): |
|
1960 ... subject = CharField() |
|
1961 ... message = CharField(widget=Textarea) |
|
1962 >>> f = ContactForm(auto_id=False) |
|
1963 >>> print f['subject'] |
|
1964 <input type="text" name="subject" /> |
|
1965 >>> print f['message'] |
|
1966 <textarea name="message"></textarea> |
|
1967 |
|
1968 as_textarea(), as_text() and as_hidden() are shortcuts for changing the output |
|
1969 widget type: |
|
1970 >>> f['subject'].as_textarea() |
|
1971 u'<textarea name="subject"></textarea>' |
|
1972 >>> f['message'].as_text() |
|
1973 u'<input type="text" name="message" />' |
|
1974 >>> f['message'].as_hidden() |
|
1975 u'<input type="hidden" name="message" />' |
|
1976 |
|
1977 The 'widget' parameter to a Field can also be an instance: |
|
1978 >>> class ContactForm(Form): |
|
1979 ... subject = CharField() |
|
1980 ... message = CharField(widget=Textarea(attrs={'rows': 80, 'cols': 20})) |
|
1981 >>> f = ContactForm(auto_id=False) |
|
1982 >>> print f['message'] |
|
1983 <textarea rows="80" cols="20" name="message"></textarea> |
|
1984 |
|
1985 Instance-level attrs are *not* carried over to as_textarea(), as_text() and |
|
1986 as_hidden(): |
|
1987 >>> f['message'].as_text() |
|
1988 u'<input type="text" name="message" />' |
|
1989 >>> f = ContactForm({'subject': 'Hello', 'message': 'I love you.'}, auto_id=False) |
|
1990 >>> f['subject'].as_textarea() |
|
1991 u'<textarea name="subject">Hello</textarea>' |
|
1992 >>> f['message'].as_text() |
|
1993 u'<input type="text" name="message" value="I love you." />' |
|
1994 >>> f['message'].as_hidden() |
|
1995 u'<input type="hidden" name="message" value="I love you." />' |
|
1996 |
|
1997 For a form with a <select>, use ChoiceField: |
|
1998 >>> class FrameworkForm(Form): |
|
1999 ... name = CharField() |
|
2000 ... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')]) |
|
2001 >>> f = FrameworkForm(auto_id=False) |
|
2002 >>> print f['language'] |
|
2003 <select name="language"> |
|
2004 <option value="P">Python</option> |
|
2005 <option value="J">Java</option> |
|
2006 </select> |
|
2007 >>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False) |
|
2008 >>> print f['language'] |
|
2009 <select name="language"> |
|
2010 <option value="P" selected="selected">Python</option> |
|
2011 <option value="J">Java</option> |
|
2012 </select> |
|
2013 |
|
2014 A subtlety: If one of the choices' value is the empty string and the form is |
|
2015 unbound, then the <option> for the empty-string choice will get selected="selected". |
|
2016 >>> class FrameworkForm(Form): |
|
2017 ... name = CharField() |
|
2018 ... language = ChoiceField(choices=[('', '------'), ('P', 'Python'), ('J', 'Java')]) |
|
2019 >>> f = FrameworkForm(auto_id=False) |
|
2020 >>> print f['language'] |
|
2021 <select name="language"> |
|
2022 <option value="" selected="selected">------</option> |
|
2023 <option value="P">Python</option> |
|
2024 <option value="J">Java</option> |
|
2025 </select> |
|
2026 |
|
2027 You can specify widget attributes in the Widget constructor. |
|
2028 >>> class FrameworkForm(Form): |
|
2029 ... name = CharField() |
|
2030 ... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=Select(attrs={'class': 'foo'})) |
|
2031 >>> f = FrameworkForm(auto_id=False) |
|
2032 >>> print f['language'] |
|
2033 <select class="foo" name="language"> |
|
2034 <option value="P">Python</option> |
|
2035 <option value="J">Java</option> |
|
2036 </select> |
|
2037 >>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False) |
|
2038 >>> print f['language'] |
|
2039 <select class="foo" name="language"> |
|
2040 <option value="P" selected="selected">Python</option> |
|
2041 <option value="J">Java</option> |
|
2042 </select> |
|
2043 |
|
2044 When passing a custom widget instance to ChoiceField, note that setting |
|
2045 'choices' on the widget is meaningless. The widget will use the choices |
|
2046 defined on the Field, not the ones defined on the Widget. |
|
2047 >>> class FrameworkForm(Form): |
|
2048 ... name = CharField() |
|
2049 ... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=Select(choices=[('R', 'Ruby'), ('P', 'Perl')], attrs={'class': 'foo'})) |
|
2050 >>> f = FrameworkForm(auto_id=False) |
|
2051 >>> print f['language'] |
|
2052 <select class="foo" name="language"> |
|
2053 <option value="P">Python</option> |
|
2054 <option value="J">Java</option> |
|
2055 </select> |
|
2056 >>> f = FrameworkForm({'name': 'Django', 'language': 'P'}, auto_id=False) |
|
2057 >>> print f['language'] |
|
2058 <select class="foo" name="language"> |
|
2059 <option value="P" selected="selected">Python</option> |
|
2060 <option value="J">Java</option> |
|
2061 </select> |
|
2062 |
|
2063 You can set a ChoiceField's choices after the fact. |
|
2064 >>> class FrameworkForm(Form): |
|
2065 ... name = CharField() |
|
2066 ... language = ChoiceField() |
|
2067 >>> f = FrameworkForm(auto_id=False) |
|
2068 >>> print f['language'] |
|
2069 <select name="language"> |
|
2070 </select> |
|
2071 >>> f.fields['language'].choices = [('P', 'Python'), ('J', 'Java')] |
|
2072 >>> print f['language'] |
|
2073 <select name="language"> |
|
2074 <option value="P">Python</option> |
|
2075 <option value="J">Java</option> |
|
2076 </select> |
|
2077 |
|
2078 Add widget=RadioSelect to use that widget with a ChoiceField. |
|
2079 >>> class FrameworkForm(Form): |
|
2080 ... name = CharField() |
|
2081 ... language = ChoiceField(choices=[('P', 'Python'), ('J', 'Java')], widget=RadioSelect) |
|
2082 >>> f = FrameworkForm(auto_id=False) |
|
2083 >>> print f['language'] |
|
2084 <ul> |
|
2085 <li><label><input type="radio" name="language" value="P" /> Python</label></li> |
|
2086 <li><label><input type="radio" name="language" value="J" /> Java</label></li> |
|
2087 </ul> |
|
2088 >>> print f |
|
2089 <tr><th>Name:</th><td><input type="text" name="name" /></td></tr> |
|
2090 <tr><th>Language:</th><td><ul> |
|
2091 <li><label><input type="radio" name="language" value="P" /> Python</label></li> |
|
2092 <li><label><input type="radio" name="language" value="J" /> Java</label></li> |
|
2093 </ul></td></tr> |
|
2094 >>> print f.as_ul() |
|
2095 <li>Name: <input type="text" name="name" /></li> |
|
2096 <li>Language: <ul> |
|
2097 <li><label><input type="radio" name="language" value="P" /> Python</label></li> |
|
2098 <li><label><input type="radio" name="language" value="J" /> Java</label></li> |
|
2099 </ul></li> |
|
2100 |
|
2101 Regarding auto_id and <label>, RadioSelect is a special case. Each radio button |
|
2102 gets a distinct ID, formed by appending an underscore plus the button's |
|
2103 zero-based index. |
|
2104 >>> f = FrameworkForm(auto_id='id_%s') |
|
2105 >>> print f['language'] |
|
2106 <ul> |
|
2107 <li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> |
|
2108 <li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> |
|
2109 </ul> |
|
2110 |
|
2111 When RadioSelect is used with auto_id, and the whole form is printed using |
|
2112 either as_table() or as_ul(), the label for the RadioSelect will point to the |
|
2113 ID of the *first* radio button. |
|
2114 >>> print f |
|
2115 <tr><th><label for="id_name">Name:</label></th><td><input type="text" name="name" id="id_name" /></td></tr> |
|
2116 <tr><th><label for="id_language_0">Language:</label></th><td><ul> |
|
2117 <li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> |
|
2118 <li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> |
|
2119 </ul></td></tr> |
|
2120 >>> print f.as_ul() |
|
2121 <li><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></li> |
|
2122 <li><label for="id_language_0">Language:</label> <ul> |
|
2123 <li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> |
|
2124 <li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> |
|
2125 </ul></li> |
|
2126 >>> print f.as_p() |
|
2127 <p><label for="id_name">Name:</label> <input type="text" name="name" id="id_name" /></p> |
|
2128 <p><label for="id_language_0">Language:</label> <ul> |
|
2129 <li><label><input type="radio" id="id_language_0" value="P" name="language" /> Python</label></li> |
|
2130 <li><label><input type="radio" id="id_language_1" value="J" name="language" /> Java</label></li> |
|
2131 </ul></p> |
|
2132 |
|
2133 MultipleChoiceField is a special case, as its data is required to be a list: |
|
2134 >>> class SongForm(Form): |
|
2135 ... name = CharField() |
|
2136 ... composers = MultipleChoiceField() |
|
2137 >>> f = SongForm(auto_id=False) |
|
2138 >>> print f['composers'] |
|
2139 <select multiple="multiple" name="composers"> |
|
2140 </select> |
|
2141 >>> class SongForm(Form): |
|
2142 ... name = CharField() |
|
2143 ... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')]) |
|
2144 >>> f = SongForm(auto_id=False) |
|
2145 >>> print f['composers'] |
|
2146 <select multiple="multiple" name="composers"> |
|
2147 <option value="J">John Lennon</option> |
|
2148 <option value="P">Paul McCartney</option> |
|
2149 </select> |
|
2150 >>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False) |
|
2151 >>> print f['name'] |
|
2152 <input type="text" name="name" value="Yesterday" /> |
|
2153 >>> print f['composers'] |
|
2154 <select multiple="multiple" name="composers"> |
|
2155 <option value="J">John Lennon</option> |
|
2156 <option value="P" selected="selected">Paul McCartney</option> |
|
2157 </select> |
|
2158 |
|
2159 MultipleChoiceField rendered as_hidden() is a special case. Because it can |
|
2160 have multiple values, its as_hidden() renders multiple <input type="hidden"> |
|
2161 tags. |
|
2162 >>> f = SongForm({'name': 'Yesterday', 'composers': ['P']}, auto_id=False) |
|
2163 >>> print f['composers'].as_hidden() |
|
2164 <input type="hidden" name="composers" value="P" /> |
|
2165 >>> f = SongForm({'name': 'From Me To You', 'composers': ['P', 'J']}, auto_id=False) |
|
2166 >>> print f['composers'].as_hidden() |
|
2167 <input type="hidden" name="composers" value="P" /> |
|
2168 <input type="hidden" name="composers" value="J" /> |
|
2169 |
|
2170 MultipleChoiceField can also be used with the CheckboxSelectMultiple widget. |
|
2171 >>> class SongForm(Form): |
|
2172 ... name = CharField() |
|
2173 ... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=CheckboxSelectMultiple) |
|
2174 >>> f = SongForm(auto_id=False) |
|
2175 >>> print f['composers'] |
|
2176 <ul> |
|
2177 <li><label><input type="checkbox" name="composers" value="J" /> John Lennon</label></li> |
|
2178 <li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> |
|
2179 </ul> |
|
2180 >>> f = SongForm({'composers': ['J']}, auto_id=False) |
|
2181 >>> print f['composers'] |
|
2182 <ul> |
|
2183 <li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li> |
|
2184 <li><label><input type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> |
|
2185 </ul> |
|
2186 >>> f = SongForm({'composers': ['J', 'P']}, auto_id=False) |
|
2187 >>> print f['composers'] |
|
2188 <ul> |
|
2189 <li><label><input checked="checked" type="checkbox" name="composers" value="J" /> John Lennon</label></li> |
|
2190 <li><label><input checked="checked" type="checkbox" name="composers" value="P" /> Paul McCartney</label></li> |
|
2191 </ul> |
|
2192 |
|
2193 Regarding auto_id, CheckboxSelectMultiple is a special case. Each checkbox |
|
2194 gets a distinct ID, formed by appending an underscore plus the checkbox's |
|
2195 zero-based index. |
|
2196 >>> f = SongForm(auto_id='%s_id') |
|
2197 >>> print f['composers'] |
|
2198 <ul> |
|
2199 <li><label><input type="checkbox" name="composers" value="J" id="composers_id_0" /> John Lennon</label></li> |
|
2200 <li><label><input type="checkbox" name="composers" value="P" id="composers_id_1" /> Paul McCartney</label></li> |
|
2201 </ul> |
|
2202 |
|
2203 Data for a MultipleChoiceField should be a list. QueryDict and MultiValueDict |
|
2204 conveniently work with this. |
|
2205 >>> data = {'name': 'Yesterday', 'composers': ['J', 'P']} |
|
2206 >>> f = SongForm(data) |
|
2207 >>> f.errors |
|
2208 {} |
|
2209 >>> from django.http import QueryDict |
|
2210 >>> data = QueryDict('name=Yesterday&composers=J&composers=P') |
|
2211 >>> f = SongForm(data) |
|
2212 >>> f.errors |
|
2213 {} |
|
2214 >>> from django.utils.datastructures import MultiValueDict |
|
2215 >>> data = MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])) |
|
2216 >>> f = SongForm(data) |
|
2217 >>> f.errors |
|
2218 {} |
|
2219 |
|
2220 The MultipleHiddenInput widget renders multiple values as hidden fields. |
|
2221 >>> class SongFormHidden(Form): |
|
2222 ... name = CharField() |
|
2223 ... composers = MultipleChoiceField(choices=[('J', 'John Lennon'), ('P', 'Paul McCartney')], widget=MultipleHiddenInput) |
|
2224 >>> f = SongFormHidden(MultiValueDict(dict(name=['Yesterday'], composers=['J', 'P'])), auto_id=False) |
|
2225 >>> print f.as_ul() |
|
2226 <li>Name: <input type="text" name="name" value="Yesterday" /><input type="hidden" name="composers" value="J" /> |
|
2227 <input type="hidden" name="composers" value="P" /></li> |
|
2228 |
|
2229 When using CheckboxSelectMultiple, the framework expects a list of input and |
|
2230 returns a list of input. |
|
2231 >>> f = SongForm({'name': 'Yesterday'}, auto_id=False) |
|
2232 >>> f.errors |
|
2233 {'composers': [u'This field is required.']} |
|
2234 >>> f = SongForm({'name': 'Yesterday', 'composers': ['J']}, auto_id=False) |
|
2235 >>> f.errors |
|
2236 {} |
|
2237 >>> f.clean_data |
|
2238 {'composers': [u'J'], 'name': u'Yesterday'} |
|
2239 >>> f = SongForm({'name': 'Yesterday', 'composers': ['J', 'P']}, auto_id=False) |
|
2240 >>> f.errors |
|
2241 {} |
|
2242 >>> f.clean_data |
|
2243 {'composers': [u'J', u'P'], 'name': u'Yesterday'} |
|
2244 |
|
2245 Validation errors are HTML-escaped when output as HTML. |
|
2246 >>> class EscapingForm(Form): |
|
2247 ... special_name = CharField() |
|
2248 ... def clean_special_name(self): |
|
2249 ... raise ValidationError("Something's wrong with '%s'" % self.clean_data['special_name']) |
|
2250 |
|
2251 >>> f = EscapingForm({'special_name': "Nothing to escape"}, auto_id=False) |
|
2252 >>> print f |
|
2253 <tr><th>Special name:</th><td><ul class="errorlist"><li>Something's wrong with 'Nothing to escape'</li></ul><input type="text" name="special_name" value="Nothing to escape" /></td></tr> |
|
2254 >>> f = EscapingForm({'special_name': "Should escape < & > and <script>alert('xss')</script>"}, auto_id=False) |
|
2255 >>> print f |
|
2256 <tr><th>Special name:</th><td><ul class="errorlist"><li>Something's wrong with 'Should escape < & > and <script>alert('xss')</script>'</li></ul><input type="text" name="special_name" value="Should escape < & > and <script>alert('xss')</script>" /></td></tr> |
|
2257 |
|
2258 # Validating multiple fields in relation to another ########################### |
|
2259 |
|
2260 There are a couple of ways to do multiple-field validation. If you want the |
|
2261 validation message to be associated with a particular field, implement the |
|
2262 clean_XXX() method on the Form, where XXX is the field name. As in |
|
2263 Field.clean(), the clean_XXX() method should return the cleaned value. In the |
|
2264 clean_XXX() method, you have access to self.clean_data, which is a dictionary |
|
2265 of all the data that has been cleaned *so far*, in order by the fields, |
|
2266 including the current field (e.g., the field XXX if you're in clean_XXX()). |
|
2267 >>> class UserRegistration(Form): |
|
2268 ... username = CharField(max_length=10) |
|
2269 ... password1 = CharField(widget=PasswordInput) |
|
2270 ... password2 = CharField(widget=PasswordInput) |
|
2271 ... def clean_password2(self): |
|
2272 ... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: |
|
2273 ... raise ValidationError(u'Please make sure your passwords match.') |
|
2274 ... return self.clean_data['password2'] |
|
2275 >>> f = UserRegistration(auto_id=False) |
|
2276 >>> f.errors |
|
2277 {} |
|
2278 >>> f = UserRegistration({}, auto_id=False) |
|
2279 >>> f.errors |
|
2280 {'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']} |
|
2281 >>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}, auto_id=False) |
|
2282 >>> f.errors |
|
2283 {'password2': [u'Please make sure your passwords match.']} |
|
2284 >>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False) |
|
2285 >>> f.errors |
|
2286 {} |
|
2287 >>> f.clean_data |
|
2288 {'username': u'adrian', 'password1': u'foo', 'password2': u'foo'} |
|
2289 |
|
2290 Another way of doing multiple-field validation is by implementing the |
|
2291 Form's clean() method. If you do this, any ValidationError raised by that |
|
2292 method will not be associated with a particular field; it will have a |
|
2293 special-case association with the field named '__all__'. |
|
2294 Note that in Form.clean(), you have access to self.clean_data, a dictionary of |
|
2295 all the fields/values that have *not* raised a ValidationError. Also note |
|
2296 Form.clean() is required to return a dictionary of all clean data. |
|
2297 >>> class UserRegistration(Form): |
|
2298 ... username = CharField(max_length=10) |
|
2299 ... password1 = CharField(widget=PasswordInput) |
|
2300 ... password2 = CharField(widget=PasswordInput) |
|
2301 ... def clean(self): |
|
2302 ... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: |
|
2303 ... raise ValidationError(u'Please make sure your passwords match.') |
|
2304 ... return self.clean_data |
|
2305 >>> f = UserRegistration(auto_id=False) |
|
2306 >>> f.errors |
|
2307 {} |
|
2308 >>> f = UserRegistration({}, auto_id=False) |
|
2309 >>> print f.as_table() |
|
2310 <tr><th>Username:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="username" maxlength="10" /></td></tr> |
|
2311 <tr><th>Password1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password1" /></td></tr> |
|
2312 <tr><th>Password2:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="password" name="password2" /></td></tr> |
|
2313 >>> f.errors |
|
2314 {'username': [u'This field is required.'], 'password1': [u'This field is required.'], 'password2': [u'This field is required.']} |
|
2315 >>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'bar'}, auto_id=False) |
|
2316 >>> f.errors |
|
2317 {'__all__': [u'Please make sure your passwords match.']} |
|
2318 >>> print f.as_table() |
|
2319 <tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> |
|
2320 <tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr> |
|
2321 <tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr> |
|
2322 <tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr> |
|
2323 >>> print f.as_ul() |
|
2324 <li><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></li> |
|
2325 <li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li> |
|
2326 <li>Password1: <input type="password" name="password1" value="foo" /></li> |
|
2327 <li>Password2: <input type="password" name="password2" value="bar" /></li> |
|
2328 >>> f = UserRegistration({'username': 'adrian', 'password1': 'foo', 'password2': 'foo'}, auto_id=False) |
|
2329 >>> f.errors |
|
2330 {} |
|
2331 >>> f.clean_data |
|
2332 {'username': u'adrian', 'password1': u'foo', 'password2': u'foo'} |
|
2333 |
|
2334 # Dynamic construction ######################################################## |
|
2335 |
|
2336 It's possible to construct a Form dynamically by adding to the self.fields |
|
2337 dictionary in __init__(). Don't forget to call Form.__init__() within the |
|
2338 subclass' __init__(). |
|
2339 >>> class Person(Form): |
|
2340 ... first_name = CharField() |
|
2341 ... last_name = CharField() |
|
2342 ... def __init__(self, *args, **kwargs): |
|
2343 ... super(Person, self).__init__(*args, **kwargs) |
|
2344 ... self.fields['birthday'] = DateField() |
|
2345 >>> p = Person(auto_id=False) |
|
2346 >>> print p |
|
2347 <tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr> |
|
2348 <tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr> |
|
2349 <tr><th>Birthday:</th><td><input type="text" name="birthday" /></td></tr> |
|
2350 |
|
2351 Instances of a dynamic Form do not persist fields from one Form instance to |
|
2352 the next. |
|
2353 >>> class MyForm(Form): |
|
2354 ... def __init__(self, data=None, auto_id=False, field_list=[]): |
|
2355 ... Form.__init__(self, data, auto_id) |
|
2356 ... for field in field_list: |
|
2357 ... self.fields[field[0]] = field[1] |
|
2358 >>> field_list = [('field1', CharField()), ('field2', CharField())] |
|
2359 >>> my_form = MyForm(field_list=field_list) |
|
2360 >>> print my_form |
|
2361 <tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr> |
|
2362 <tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr> |
|
2363 >>> field_list = [('field3', CharField()), ('field4', CharField())] |
|
2364 >>> my_form = MyForm(field_list=field_list) |
|
2365 >>> print my_form |
|
2366 <tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr> |
|
2367 <tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr> |
|
2368 |
|
2369 >>> class MyForm(Form): |
|
2370 ... default_field_1 = CharField() |
|
2371 ... default_field_2 = CharField() |
|
2372 ... def __init__(self, data=None, auto_id=False, field_list=[]): |
|
2373 ... Form.__init__(self, data, auto_id) |
|
2374 ... for field in field_list: |
|
2375 ... self.fields[field[0]] = field[1] |
|
2376 >>> field_list = [('field1', CharField()), ('field2', CharField())] |
|
2377 >>> my_form = MyForm(field_list=field_list) |
|
2378 >>> print my_form |
|
2379 <tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr> |
|
2380 <tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr> |
|
2381 <tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr> |
|
2382 <tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr> |
|
2383 >>> field_list = [('field3', CharField()), ('field4', CharField())] |
|
2384 >>> my_form = MyForm(field_list=field_list) |
|
2385 >>> print my_form |
|
2386 <tr><th>Default field 1:</th><td><input type="text" name="default_field_1" /></td></tr> |
|
2387 <tr><th>Default field 2:</th><td><input type="text" name="default_field_2" /></td></tr> |
|
2388 <tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr> |
|
2389 <tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr> |
|
2390 |
|
2391 Similarly, changes to field attributes do not persist from one Form instance |
|
2392 to the next. |
|
2393 >>> class Person(Form): |
|
2394 ... first_name = CharField(required=False) |
|
2395 ... last_name = CharField(required=False) |
|
2396 ... def __init__(self, names_required=False, *args, **kwargs): |
|
2397 ... super(Person, self).__init__(*args, **kwargs) |
|
2398 ... if names_required: |
|
2399 ... self.fields['first_name'].required = True |
|
2400 ... self.fields['last_name'].required = True |
|
2401 >>> f = Person(names_required=False) |
|
2402 >>> f['first_name'].field.required, f['last_name'].field.required |
|
2403 (False, False) |
|
2404 >>> f = Person(names_required=True) |
|
2405 >>> f['first_name'].field.required, f['last_name'].field.required |
|
2406 (True, True) |
|
2407 >>> f = Person(names_required=False) |
|
2408 >>> f['first_name'].field.required, f['last_name'].field.required |
|
2409 (False, False) |
|
2410 >>> class Person(Form): |
|
2411 ... first_name = CharField(max_length=30) |
|
2412 ... last_name = CharField(max_length=30) |
|
2413 ... def __init__(self, name_max_length=None, *args, **kwargs): |
|
2414 ... super(Person, self).__init__(*args, **kwargs) |
|
2415 ... if name_max_length: |
|
2416 ... self.fields['first_name'].max_length = name_max_length |
|
2417 ... self.fields['last_name'].max_length = name_max_length |
|
2418 >>> f = Person(name_max_length=None) |
|
2419 >>> f['first_name'].field.max_length, f['last_name'].field.max_length |
|
2420 (30, 30) |
|
2421 >>> f = Person(name_max_length=20) |
|
2422 >>> f['first_name'].field.max_length, f['last_name'].field.max_length |
|
2423 (20, 20) |
|
2424 >>> f = Person(name_max_length=None) |
|
2425 >>> f['first_name'].field.max_length, f['last_name'].field.max_length |
|
2426 (30, 30) |
|
2427 |
|
2428 HiddenInput widgets are displayed differently in the as_table(), as_ul() |
|
2429 and as_p() output of a Form -- their verbose names are not displayed, and a |
|
2430 separate row is not displayed. They're displayed in the last row of the |
|
2431 form, directly after that row's form element. |
|
2432 >>> class Person(Form): |
|
2433 ... first_name = CharField() |
|
2434 ... last_name = CharField() |
|
2435 ... hidden_text = CharField(widget=HiddenInput) |
|
2436 ... birthday = DateField() |
|
2437 >>> p = Person(auto_id=False) |
|
2438 >>> print p |
|
2439 <tr><th>First name:</th><td><input type="text" name="first_name" /></td></tr> |
|
2440 <tr><th>Last name:</th><td><input type="text" name="last_name" /></td></tr> |
|
2441 <tr><th>Birthday:</th><td><input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></td></tr> |
|
2442 >>> print p.as_ul() |
|
2443 <li>First name: <input type="text" name="first_name" /></li> |
|
2444 <li>Last name: <input type="text" name="last_name" /></li> |
|
2445 <li>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></li> |
|
2446 >>> print p.as_p() |
|
2447 <p>First name: <input type="text" name="first_name" /></p> |
|
2448 <p>Last name: <input type="text" name="last_name" /></p> |
|
2449 <p>Birthday: <input type="text" name="birthday" /><input type="hidden" name="hidden_text" /></p> |
|
2450 |
|
2451 With auto_id set, a HiddenInput still gets an ID, but it doesn't get a label. |
|
2452 >>> p = Person(auto_id='id_%s') |
|
2453 >>> print p |
|
2454 <tr><th><label for="id_first_name">First name:</label></th><td><input type="text" name="first_name" id="id_first_name" /></td></tr> |
|
2455 <tr><th><label for="id_last_name">Last name:</label></th><td><input type="text" name="last_name" id="id_last_name" /></td></tr> |
|
2456 <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> |
|
2457 >>> print p.as_ul() |
|
2458 <li><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></li> |
|
2459 <li><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></li> |
|
2460 <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> |
|
2461 >>> print p.as_p() |
|
2462 <p><label for="id_first_name">First name:</label> <input type="text" name="first_name" id="id_first_name" /></p> |
|
2463 <p><label for="id_last_name">Last name:</label> <input type="text" name="last_name" id="id_last_name" /></p> |
|
2464 <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> |
|
2465 |
|
2466 If a field with a HiddenInput has errors, the as_table() and as_ul() output |
|
2467 will include the error message(s) with the text "(Hidden field [fieldname]) " |
|
2468 prepended. This message is displayed at the top of the output, regardless of |
|
2469 its field's order in the form. |
|
2470 >>> p = Person({'first_name': 'John', 'last_name': 'Lennon', 'birthday': '1940-10-9'}, auto_id=False) |
|
2471 >>> print p |
|
2472 <tr><td colspan="2"><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></td></tr> |
|
2473 <tr><th>First name:</th><td><input type="text" name="first_name" value="John" /></td></tr> |
|
2474 <tr><th>Last name:</th><td><input type="text" name="last_name" value="Lennon" /></td></tr> |
|
2475 <tr><th>Birthday:</th><td><input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></td></tr> |
|
2476 >>> print p.as_ul() |
|
2477 <li><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></li> |
|
2478 <li>First name: <input type="text" name="first_name" value="John" /></li> |
|
2479 <li>Last name: <input type="text" name="last_name" value="Lennon" /></li> |
|
2480 <li>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></li> |
|
2481 >>> print p.as_p() |
|
2482 <p><ul class="errorlist"><li>(Hidden field hidden_text) This field is required.</li></ul></p> |
|
2483 <p>First name: <input type="text" name="first_name" value="John" /></p> |
|
2484 <p>Last name: <input type="text" name="last_name" value="Lennon" /></p> |
|
2485 <p>Birthday: <input type="text" name="birthday" value="1940-10-9" /><input type="hidden" name="hidden_text" /></p> |
|
2486 |
|
2487 A corner case: It's possible for a form to have only HiddenInputs. |
|
2488 >>> class TestForm(Form): |
|
2489 ... foo = CharField(widget=HiddenInput) |
|
2490 ... bar = CharField(widget=HiddenInput) |
|
2491 >>> p = TestForm(auto_id=False) |
|
2492 >>> print p.as_table() |
|
2493 <input type="hidden" name="foo" /><input type="hidden" name="bar" /> |
|
2494 >>> print p.as_ul() |
|
2495 <input type="hidden" name="foo" /><input type="hidden" name="bar" /> |
|
2496 >>> print p.as_p() |
|
2497 <input type="hidden" name="foo" /><input type="hidden" name="bar" /> |
|
2498 |
|
2499 A Form's fields are displayed in the same order in which they were defined. |
|
2500 >>> class TestForm(Form): |
|
2501 ... field1 = CharField() |
|
2502 ... field2 = CharField() |
|
2503 ... field3 = CharField() |
|
2504 ... field4 = CharField() |
|
2505 ... field5 = CharField() |
|
2506 ... field6 = CharField() |
|
2507 ... field7 = CharField() |
|
2508 ... field8 = CharField() |
|
2509 ... field9 = CharField() |
|
2510 ... field10 = CharField() |
|
2511 ... field11 = CharField() |
|
2512 ... field12 = CharField() |
|
2513 ... field13 = CharField() |
|
2514 ... field14 = CharField() |
|
2515 >>> p = TestForm(auto_id=False) |
|
2516 >>> print p |
|
2517 <tr><th>Field1:</th><td><input type="text" name="field1" /></td></tr> |
|
2518 <tr><th>Field2:</th><td><input type="text" name="field2" /></td></tr> |
|
2519 <tr><th>Field3:</th><td><input type="text" name="field3" /></td></tr> |
|
2520 <tr><th>Field4:</th><td><input type="text" name="field4" /></td></tr> |
|
2521 <tr><th>Field5:</th><td><input type="text" name="field5" /></td></tr> |
|
2522 <tr><th>Field6:</th><td><input type="text" name="field6" /></td></tr> |
|
2523 <tr><th>Field7:</th><td><input type="text" name="field7" /></td></tr> |
|
2524 <tr><th>Field8:</th><td><input type="text" name="field8" /></td></tr> |
|
2525 <tr><th>Field9:</th><td><input type="text" name="field9" /></td></tr> |
|
2526 <tr><th>Field10:</th><td><input type="text" name="field10" /></td></tr> |
|
2527 <tr><th>Field11:</th><td><input type="text" name="field11" /></td></tr> |
|
2528 <tr><th>Field12:</th><td><input type="text" name="field12" /></td></tr> |
|
2529 <tr><th>Field13:</th><td><input type="text" name="field13" /></td></tr> |
|
2530 <tr><th>Field14:</th><td><input type="text" name="field14" /></td></tr> |
|
2531 |
|
2532 Some Field classes have an effect on the HTML attributes of their associated |
|
2533 Widget. If you set max_length in a CharField and its associated widget is |
|
2534 either a TextInput or PasswordInput, then the widget's rendered HTML will |
|
2535 include the "maxlength" attribute. |
|
2536 >>> class UserRegistration(Form): |
|
2537 ... username = CharField(max_length=10) # uses TextInput by default |
|
2538 ... password = CharField(max_length=10, widget=PasswordInput) |
|
2539 ... realname = CharField(max_length=10, widget=TextInput) # redundantly define widget, just to test |
|
2540 ... address = CharField() # no max_length defined here |
|
2541 >>> p = UserRegistration(auto_id=False) |
|
2542 >>> print p.as_ul() |
|
2543 <li>Username: <input type="text" name="username" maxlength="10" /></li> |
|
2544 <li>Password: <input type="password" name="password" maxlength="10" /></li> |
|
2545 <li>Realname: <input type="text" name="realname" maxlength="10" /></li> |
|
2546 <li>Address: <input type="text" name="address" /></li> |
|
2547 |
|
2548 If you specify a custom "attrs" that includes the "maxlength" attribute, |
|
2549 the Field's max_length attribute will override whatever "maxlength" you specify |
|
2550 in "attrs". |
|
2551 >>> class UserRegistration(Form): |
|
2552 ... username = CharField(max_length=10, widget=TextInput(attrs={'maxlength': 20})) |
|
2553 ... password = CharField(max_length=10, widget=PasswordInput) |
|
2554 >>> p = UserRegistration(auto_id=False) |
|
2555 >>> print p.as_ul() |
|
2556 <li>Username: <input type="text" name="username" maxlength="10" /></li> |
|
2557 <li>Password: <input type="password" name="password" maxlength="10" /></li> |
|
2558 |
|
2559 # Specifying labels ########################################################### |
|
2560 |
|
2561 You can specify the label for a field by using the 'label' argument to a Field |
|
2562 class. If you don't specify 'label', Django will use the field name with |
|
2563 underscores converted to spaces, and the initial letter capitalized. |
|
2564 >>> class UserRegistration(Form): |
|
2565 ... username = CharField(max_length=10, label='Your username') |
|
2566 ... password1 = CharField(widget=PasswordInput) |
|
2567 ... password2 = CharField(widget=PasswordInput, label='Password (again)') |
|
2568 >>> p = UserRegistration(auto_id=False) |
|
2569 >>> print p.as_ul() |
|
2570 <li>Your username: <input type="text" name="username" maxlength="10" /></li> |
|
2571 <li>Password1: <input type="password" name="password1" /></li> |
|
2572 <li>Password (again): <input type="password" name="password2" /></li> |
|
2573 |
|
2574 A label can be a Unicode object or a bytestring with special characters. |
|
2575 >>> class UserRegistration(Form): |
|
2576 ... username = CharField(max_length=10, label='ŠĐĆŽćžšđ') |
|
2577 ... password = CharField(widget=PasswordInput, label=u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111') |
|
2578 >>> p = UserRegistration(auto_id=False) |
|
2579 >>> p.as_ul() |
|
2580 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>' |
|
2581 |
|
2582 If a label is set to the empty string for a field, that field won't get a label. |
|
2583 >>> class UserRegistration(Form): |
|
2584 ... username = CharField(max_length=10, label='') |
|
2585 ... password = CharField(widget=PasswordInput) |
|
2586 >>> p = UserRegistration(auto_id=False) |
|
2587 >>> print p.as_ul() |
|
2588 <li> <input type="text" name="username" maxlength="10" /></li> |
|
2589 <li>Password: <input type="password" name="password" /></li> |
|
2590 >>> p = UserRegistration(auto_id='id_%s') |
|
2591 >>> print p.as_ul() |
|
2592 <li> <input id="id_username" type="text" name="username" maxlength="10" /></li> |
|
2593 <li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li> |
|
2594 |
|
2595 If label is None, Django will auto-create the label from the field name. This |
|
2596 is default behavior. |
|
2597 >>> class UserRegistration(Form): |
|
2598 ... username = CharField(max_length=10, label=None) |
|
2599 ... password = CharField(widget=PasswordInput) |
|
2600 >>> p = UserRegistration(auto_id=False) |
|
2601 >>> print p.as_ul() |
|
2602 <li>Username: <input type="text" name="username" maxlength="10" /></li> |
|
2603 <li>Password: <input type="password" name="password" /></li> |
|
2604 >>> p = UserRegistration(auto_id='id_%s') |
|
2605 >>> print p.as_ul() |
|
2606 <li><label for="id_username">Username:</label> <input id="id_username" type="text" name="username" maxlength="10" /></li> |
|
2607 <li><label for="id_password">Password:</label> <input type="password" name="password" id="id_password" /></li> |
|
2608 |
|
2609 # Initial data ################################################################ |
|
2610 |
|
2611 You can specify initial data for a field by using the 'initial' argument to a |
|
2612 Field class. This initial data is displayed when a Form is rendered with *no* |
|
2613 data. It is not displayed when a Form is rendered with any data (including an |
|
2614 empty dictionary). Also, the initial value is *not* used if data for a |
|
2615 particular required field isn't provided. |
|
2616 >>> class UserRegistration(Form): |
|
2617 ... username = CharField(max_length=10, initial='django') |
|
2618 ... password = CharField(widget=PasswordInput) |
|
2619 |
|
2620 Here, we're not submitting any data, so the initial value will be displayed. |
|
2621 >>> p = UserRegistration(auto_id=False) |
|
2622 >>> print p.as_ul() |
|
2623 <li>Username: <input type="text" name="username" value="django" maxlength="10" /></li> |
|
2624 <li>Password: <input type="password" name="password" /></li> |
|
2625 |
|
2626 Here, we're submitting data, so the initial value will *not* be displayed. |
|
2627 >>> p = UserRegistration({}, auto_id=False) |
|
2628 >>> print p.as_ul() |
|
2629 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> |
|
2630 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> |
|
2631 >>> p = UserRegistration({'username': u''}, auto_id=False) |
|
2632 >>> print p.as_ul() |
|
2633 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> |
|
2634 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> |
|
2635 >>> p = UserRegistration({'username': u'foo'}, auto_id=False) |
|
2636 >>> print p.as_ul() |
|
2637 <li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li> |
|
2638 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> |
|
2639 |
|
2640 An 'initial' value is *not* used as a fallback if data is not provided. In this |
|
2641 example, we don't provide a value for 'username', and the form raises a |
|
2642 validation error rather than using the initial value for 'username'. |
|
2643 >>> p = UserRegistration({'password': 'secret'}) |
|
2644 >>> p.errors |
|
2645 {'username': [u'This field is required.']} |
|
2646 >>> p.is_valid() |
|
2647 False |
|
2648 |
|
2649 # Dynamic initial data ######################################################## |
|
2650 |
|
2651 The previous technique dealt with "hard-coded" initial data, but it's also |
|
2652 possible to specify initial data after you've already created the Form class |
|
2653 (i.e., at runtime). Use the 'initial' parameter to the Form constructor. This |
|
2654 should be a dictionary containing initial values for one or more fields in the |
|
2655 form, keyed by field name. |
|
2656 |
|
2657 >>> class UserRegistration(Form): |
|
2658 ... username = CharField(max_length=10) |
|
2659 ... password = CharField(widget=PasswordInput) |
|
2660 |
|
2661 Here, we're not submitting any data, so the initial value will be displayed. |
|
2662 >>> p = UserRegistration(initial={'username': 'django'}, auto_id=False) |
|
2663 >>> print p.as_ul() |
|
2664 <li>Username: <input type="text" name="username" value="django" maxlength="10" /></li> |
|
2665 <li>Password: <input type="password" name="password" /></li> |
|
2666 >>> p = UserRegistration(initial={'username': 'stephane'}, auto_id=False) |
|
2667 >>> print p.as_ul() |
|
2668 <li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li> |
|
2669 <li>Password: <input type="password" name="password" /></li> |
|
2670 |
|
2671 The 'initial' parameter is meaningless if you pass data. |
|
2672 >>> p = UserRegistration({}, initial={'username': 'django'}, auto_id=False) |
|
2673 >>> print p.as_ul() |
|
2674 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> |
|
2675 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> |
|
2676 >>> p = UserRegistration({'username': u''}, initial={'username': 'django'}, auto_id=False) |
|
2677 >>> print p.as_ul() |
|
2678 <li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li> |
|
2679 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> |
|
2680 >>> p = UserRegistration({'username': u'foo'}, initial={'username': 'django'}, auto_id=False) |
|
2681 >>> print p.as_ul() |
|
2682 <li>Username: <input type="text" name="username" value="foo" maxlength="10" /></li> |
|
2683 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /></li> |
|
2684 |
|
2685 A dynamic 'initial' value is *not* used as a fallback if data is not provided. |
|
2686 In this example, we don't provide a value for 'username', and the form raises a |
|
2687 validation error rather than using the initial value for 'username'. |
|
2688 >>> p = UserRegistration({'password': 'secret'}, initial={'username': 'django'}) |
|
2689 >>> p.errors |
|
2690 {'username': [u'This field is required.']} |
|
2691 >>> p.is_valid() |
|
2692 False |
|
2693 |
|
2694 If a Form defines 'initial' *and* 'initial' is passed as a parameter to Form(), |
|
2695 then the latter will get precedence. |
|
2696 >>> class UserRegistration(Form): |
|
2697 ... username = CharField(max_length=10, initial='django') |
|
2698 ... password = CharField(widget=PasswordInput) |
|
2699 >>> p = UserRegistration(initial={'username': 'babik'}, auto_id=False) |
|
2700 >>> print p.as_ul() |
|
2701 <li>Username: <input type="text" name="username" value="babik" maxlength="10" /></li> |
|
2702 <li>Password: <input type="password" name="password" /></li> |
|
2703 |
|
2704 # Help text ################################################################### |
|
2705 |
|
2706 You can specify descriptive text for a field by using the 'help_text' argument |
|
2707 to a Field class. This help text is displayed when a Form is rendered. |
|
2708 >>> class UserRegistration(Form): |
|
2709 ... username = CharField(max_length=10, help_text='e.g., user@example.com') |
|
2710 ... password = CharField(widget=PasswordInput, help_text='Choose wisely.') |
|
2711 >>> p = UserRegistration(auto_id=False) |
|
2712 >>> print p.as_ul() |
|
2713 <li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li> |
|
2714 <li>Password: <input type="password" name="password" /> Choose wisely.</li> |
|
2715 >>> print p.as_p() |
|
2716 <p>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</p> |
|
2717 <p>Password: <input type="password" name="password" /> Choose wisely.</p> |
|
2718 >>> print p.as_table() |
|
2719 <tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /><br />e.g., user@example.com</td></tr> |
|
2720 <tr><th>Password:</th><td><input type="password" name="password" /><br />Choose wisely.</td></tr> |
|
2721 |
|
2722 The help text is displayed whether or not data is provided for the form. |
|
2723 >>> p = UserRegistration({'username': u'foo'}, auto_id=False) |
|
2724 >>> print p.as_ul() |
|
2725 <li>Username: <input type="text" name="username" value="foo" maxlength="10" /> e.g., user@example.com</li> |
|
2726 <li><ul class="errorlist"><li>This field is required.</li></ul>Password: <input type="password" name="password" /> Choose wisely.</li> |
|
2727 |
|
2728 help_text is not displayed for hidden fields. It can be used for documentation |
|
2729 purposes, though. |
|
2730 >>> class UserRegistration(Form): |
|
2731 ... username = CharField(max_length=10, help_text='e.g., user@example.com') |
|
2732 ... password = CharField(widget=PasswordInput) |
|
2733 ... next = CharField(widget=HiddenInput, initial='/', help_text='Redirect destination') |
|
2734 >>> p = UserRegistration(auto_id=False) |
|
2735 >>> print p.as_ul() |
|
2736 <li>Username: <input type="text" name="username" maxlength="10" /> e.g., user@example.com</li> |
|
2737 <li>Password: <input type="password" name="password" /><input type="hidden" name="next" value="/" /></li> |
|
2738 |
|
2739 Help text can include arbitrary Unicode characters. |
|
2740 >>> class UserRegistration(Form): |
|
2741 ... username = CharField(max_length=10, help_text='ŠĐĆŽćžšđ') |
|
2742 >>> p = UserRegistration(auto_id=False) |
|
2743 >>> p.as_ul() |
|
2744 u'<li>Username: <input type="text" name="username" maxlength="10" /> \u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111</li>' |
|
2745 |
|
2746 # Subclassing forms ########################################################### |
|
2747 |
|
2748 You can subclass a Form to add fields. The resulting form subclass will have |
|
2749 all of the fields of the parent Form, plus whichever fields you define in the |
|
2750 subclass. |
|
2751 >>> class Person(Form): |
|
2752 ... first_name = CharField() |
|
2753 ... last_name = CharField() |
|
2754 ... birthday = DateField() |
|
2755 >>> class Musician(Person): |
|
2756 ... instrument = CharField() |
|
2757 >>> p = Person(auto_id=False) |
|
2758 >>> print p.as_ul() |
|
2759 <li>First name: <input type="text" name="first_name" /></li> |
|
2760 <li>Last name: <input type="text" name="last_name" /></li> |
|
2761 <li>Birthday: <input type="text" name="birthday" /></li> |
|
2762 >>> m = Musician(auto_id=False) |
|
2763 >>> print m.as_ul() |
|
2764 <li>First name: <input type="text" name="first_name" /></li> |
|
2765 <li>Last name: <input type="text" name="last_name" /></li> |
|
2766 <li>Birthday: <input type="text" name="birthday" /></li> |
|
2767 <li>Instrument: <input type="text" name="instrument" /></li> |
|
2768 |
|
2769 Yes, you can subclass multiple forms. The fields are added in the order in |
|
2770 which the parent classes are listed. |
|
2771 >>> class Person(Form): |
|
2772 ... first_name = CharField() |
|
2773 ... last_name = CharField() |
|
2774 ... birthday = DateField() |
|
2775 >>> class Instrument(Form): |
|
2776 ... instrument = CharField() |
|
2777 >>> class Beatle(Person, Instrument): |
|
2778 ... haircut_type = CharField() |
|
2779 >>> b = Beatle(auto_id=False) |
|
2780 >>> print b.as_ul() |
|
2781 <li>First name: <input type="text" name="first_name" /></li> |
|
2782 <li>Last name: <input type="text" name="last_name" /></li> |
|
2783 <li>Birthday: <input type="text" name="birthday" /></li> |
|
2784 <li>Instrument: <input type="text" name="instrument" /></li> |
|
2785 <li>Haircut type: <input type="text" name="haircut_type" /></li> |
|
2786 |
|
2787 # Forms with prefixes ######################################################### |
|
2788 |
|
2789 Sometimes it's necessary to have multiple forms display on the same HTML page, |
|
2790 or multiple copies of the same form. We can accomplish this with form prefixes. |
|
2791 Pass the keyword argument 'prefix' to the Form constructor to use this feature. |
|
2792 This value will be prepended to each HTML form field name. One way to think |
|
2793 about this is "namespaces for HTML forms". Notice that in the data argument, |
|
2794 each field's key has the prefix, in this case 'person1', prepended to the |
|
2795 actual field name. |
|
2796 >>> class Person(Form): |
|
2797 ... first_name = CharField() |
|
2798 ... last_name = CharField() |
|
2799 ... birthday = DateField() |
|
2800 >>> data = { |
|
2801 ... 'person1-first_name': u'John', |
|
2802 ... 'person1-last_name': u'Lennon', |
|
2803 ... 'person1-birthday': u'1940-10-9' |
|
2804 ... } |
|
2805 >>> p = Person(data, prefix='person1') |
|
2806 >>> print p.as_ul() |
|
2807 <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> |
|
2808 <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> |
|
2809 <li><label for="id_person1-birthday">Birthday:</label> <input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /></li> |
|
2810 >>> print p['first_name'] |
|
2811 <input type="text" name="person1-first_name" value="John" id="id_person1-first_name" /> |
|
2812 >>> print p['last_name'] |
|
2813 <input type="text" name="person1-last_name" value="Lennon" id="id_person1-last_name" /> |
|
2814 >>> print p['birthday'] |
|
2815 <input type="text" name="person1-birthday" value="1940-10-9" id="id_person1-birthday" /> |
|
2816 >>> p.errors |
|
2817 {} |
|
2818 >>> p.is_valid() |
|
2819 True |
|
2820 >>> p.clean_data |
|
2821 {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} |
|
2822 |
|
2823 Let's try submitting some bad data to make sure form.errors and field.errors |
|
2824 work as expected. |
|
2825 >>> data = { |
|
2826 ... 'person1-first_name': u'', |
|
2827 ... 'person1-last_name': u'', |
|
2828 ... 'person1-birthday': u'' |
|
2829 ... } |
|
2830 >>> p = Person(data, prefix='person1') |
|
2831 >>> p.errors |
|
2832 {'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} |
|
2833 >>> p['first_name'].errors |
|
2834 [u'This field is required.'] |
|
2835 >>> p['person1-first_name'].errors |
|
2836 Traceback (most recent call last): |
|
2837 ... |
|
2838 KeyError: "Key 'person1-first_name' not found in Form" |
|
2839 |
|
2840 In this example, the data doesn't have a prefix, but the form requires it, so |
|
2841 the form doesn't "see" the fields. |
|
2842 >>> data = { |
|
2843 ... 'first_name': u'John', |
|
2844 ... 'last_name': u'Lennon', |
|
2845 ... 'birthday': u'1940-10-9' |
|
2846 ... } |
|
2847 >>> p = Person(data, prefix='person1') |
|
2848 >>> p.errors |
|
2849 {'first_name': [u'This field is required.'], 'last_name': [u'This field is required.'], 'birthday': [u'This field is required.']} |
|
2850 |
|
2851 With prefixes, a single data dictionary can hold data for multiple instances |
|
2852 of the same form. |
|
2853 >>> data = { |
|
2854 ... 'person1-first_name': u'John', |
|
2855 ... 'person1-last_name': u'Lennon', |
|
2856 ... 'person1-birthday': u'1940-10-9', |
|
2857 ... 'person2-first_name': u'Jim', |
|
2858 ... 'person2-last_name': u'Morrison', |
|
2859 ... 'person2-birthday': u'1943-12-8' |
|
2860 ... } |
|
2861 >>> p1 = Person(data, prefix='person1') |
|
2862 >>> p1.is_valid() |
|
2863 True |
|
2864 >>> p1.clean_data |
|
2865 {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} |
|
2866 >>> p2 = Person(data, prefix='person2') |
|
2867 >>> p2.is_valid() |
|
2868 True |
|
2869 >>> p2.clean_data |
|
2870 {'first_name': u'Jim', 'last_name': u'Morrison', 'birthday': datetime.date(1943, 12, 8)} |
|
2871 |
|
2872 By default, forms append a hyphen between the prefix and the field name, but a |
|
2873 form can alter that behavior by implementing the add_prefix() method. This |
|
2874 method takes a field name and returns the prefixed field, according to |
|
2875 self.prefix. |
|
2876 >>> class Person(Form): |
|
2877 ... first_name = CharField() |
|
2878 ... last_name = CharField() |
|
2879 ... birthday = DateField() |
|
2880 ... def add_prefix(self, field_name): |
|
2881 ... return self.prefix and '%s-prefix-%s' % (self.prefix, field_name) or field_name |
|
2882 >>> p = Person(prefix='foo') |
|
2883 >>> print p.as_ul() |
|
2884 <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> |
|
2885 <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> |
|
2886 <li><label for="id_foo-prefix-birthday">Birthday:</label> <input type="text" name="foo-prefix-birthday" id="id_foo-prefix-birthday" /></li> |
|
2887 >>> data = { |
|
2888 ... 'foo-prefix-first_name': u'John', |
|
2889 ... 'foo-prefix-last_name': u'Lennon', |
|
2890 ... 'foo-prefix-birthday': u'1940-10-9' |
|
2891 ... } |
|
2892 >>> p = Person(data, prefix='foo') |
|
2893 >>> p.is_valid() |
|
2894 True |
|
2895 >>> p.clean_data |
|
2896 {'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)} |
|
2897 |
|
2898 # Forms with NullBooleanFields ################################################ |
|
2899 |
|
2900 NullBooleanField is a bit of a special case because its presentation (widget) |
|
2901 is different than its data. This is handled transparently, though. |
|
2902 |
|
2903 >>> class Person(Form): |
|
2904 ... name = CharField() |
|
2905 ... is_cool = NullBooleanField() |
|
2906 >>> p = Person({'name': u'Joe'}, auto_id=False) |
|
2907 >>> print p['is_cool'] |
|
2908 <select name="is_cool"> |
|
2909 <option value="1" selected="selected">Unknown</option> |
|
2910 <option value="2">Yes</option> |
|
2911 <option value="3">No</option> |
|
2912 </select> |
|
2913 >>> p = Person({'name': u'Joe', 'is_cool': u'1'}, auto_id=False) |
|
2914 >>> print p['is_cool'] |
|
2915 <select name="is_cool"> |
|
2916 <option value="1" selected="selected">Unknown</option> |
|
2917 <option value="2">Yes</option> |
|
2918 <option value="3">No</option> |
|
2919 </select> |
|
2920 >>> p = Person({'name': u'Joe', 'is_cool': u'2'}, auto_id=False) |
|
2921 >>> print p['is_cool'] |
|
2922 <select name="is_cool"> |
|
2923 <option value="1">Unknown</option> |
|
2924 <option value="2" selected="selected">Yes</option> |
|
2925 <option value="3">No</option> |
|
2926 </select> |
|
2927 >>> p = Person({'name': u'Joe', 'is_cool': u'3'}, auto_id=False) |
|
2928 >>> print p['is_cool'] |
|
2929 <select name="is_cool"> |
|
2930 <option value="1">Unknown</option> |
|
2931 <option value="2">Yes</option> |
|
2932 <option value="3" selected="selected">No</option> |
|
2933 </select> |
|
2934 >>> p = Person({'name': u'Joe', 'is_cool': True}, auto_id=False) |
|
2935 >>> print p['is_cool'] |
|
2936 <select name="is_cool"> |
|
2937 <option value="1">Unknown</option> |
|
2938 <option value="2" selected="selected">Yes</option> |
|
2939 <option value="3">No</option> |
|
2940 </select> |
|
2941 >>> p = Person({'name': u'Joe', 'is_cool': False}, auto_id=False) |
|
2942 >>> print p['is_cool'] |
|
2943 <select name="is_cool"> |
|
2944 <option value="1">Unknown</option> |
|
2945 <option value="2">Yes</option> |
|
2946 <option value="3" selected="selected">No</option> |
|
2947 </select> |
|
2948 |
|
2949 # Basic form processing in a view ############################################# |
|
2950 |
|
2951 >>> from django.template import Template, Context |
|
2952 >>> class UserRegistration(Form): |
|
2953 ... username = CharField(max_length=10) |
|
2954 ... password1 = CharField(widget=PasswordInput) |
|
2955 ... password2 = CharField(widget=PasswordInput) |
|
2956 ... def clean(self): |
|
2957 ... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: |
|
2958 ... raise ValidationError(u'Please make sure your passwords match.') |
|
2959 ... return self.clean_data |
|
2960 >>> def my_function(method, post_data): |
|
2961 ... if method == 'POST': |
|
2962 ... form = UserRegistration(post_data, auto_id=False) |
|
2963 ... else: |
|
2964 ... form = UserRegistration(auto_id=False) |
|
2965 ... if form.is_valid(): |
|
2966 ... return 'VALID: %r' % form.clean_data |
|
2967 ... t = Template('<form action="" method="post">\n<table>\n{{ form }}\n</table>\n<input type="submit" />\n</form>') |
|
2968 ... return t.render(Context({'form': form})) |
|
2969 |
|
2970 Case 1: GET (an empty form, with no errors). |
|
2971 >>> print my_function('GET', {}) |
|
2972 <form action="" method="post"> |
|
2973 <table> |
|
2974 <tr><th>Username:</th><td><input type="text" name="username" maxlength="10" /></td></tr> |
|
2975 <tr><th>Password1:</th><td><input type="password" name="password1" /></td></tr> |
|
2976 <tr><th>Password2:</th><td><input type="password" name="password2" /></td></tr> |
|
2977 </table> |
|
2978 <input type="submit" /> |
|
2979 </form> |
|
2980 |
|
2981 Case 2: POST with erroneous data (a redisplayed form, with errors). |
|
2982 >>> print my_function('POST', {'username': 'this-is-a-long-username', 'password1': 'foo', 'password2': 'bar'}) |
|
2983 <form action="" method="post"> |
|
2984 <table> |
|
2985 <tr><td colspan="2"><ul class="errorlist"><li>Please make sure your passwords match.</li></ul></td></tr> |
|
2986 <tr><th>Username:</th><td><ul class="errorlist"><li>Ensure this value has at most 10 characters.</li></ul><input type="text" name="username" value="this-is-a-long-username" maxlength="10" /></td></tr> |
|
2987 <tr><th>Password1:</th><td><input type="password" name="password1" value="foo" /></td></tr> |
|
2988 <tr><th>Password2:</th><td><input type="password" name="password2" value="bar" /></td></tr> |
|
2989 </table> |
|
2990 <input type="submit" /> |
|
2991 </form> |
|
2992 |
|
2993 Case 3: POST with valid data (the success message). |
|
2994 >>> print my_function('POST', {'username': 'adrian', 'password1': 'secret', 'password2': 'secret'}) |
|
2995 VALID: {'username': u'adrian', 'password1': u'secret', 'password2': u'secret'} |
|
2996 |
|
2997 # Some ideas for using templates with forms ################################### |
|
2998 |
|
2999 >>> class UserRegistration(Form): |
|
3000 ... username = CharField(max_length=10, help_text="Good luck picking a username that doesn't already exist.") |
|
3001 ... password1 = CharField(widget=PasswordInput) |
|
3002 ... password2 = CharField(widget=PasswordInput) |
|
3003 ... def clean(self): |
|
3004 ... if self.clean_data.get('password1') and self.clean_data.get('password2') and self.clean_data['password1'] != self.clean_data['password2']: |
|
3005 ... raise ValidationError(u'Please make sure your passwords match.') |
|
3006 ... return self.clean_data |
|
3007 |
|
3008 You have full flexibility in displaying form fields in a template. Just pass a |
|
3009 Form instance to the template, and use "dot" access to refer to individual |
|
3010 fields. Note, however, that this flexibility comes with the responsibility of |
|
3011 displaying all the errors, including any that might not be associated with a |
|
3012 particular field. |
|
3013 >>> t = Template('''<form action=""> |
|
3014 ... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> |
|
3015 ... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> |
|
3016 ... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> |
|
3017 ... <input type="submit" /> |
|
3018 ... </form>''') |
|
3019 >>> print t.render(Context({'form': UserRegistration(auto_id=False)})) |
|
3020 <form action=""> |
|
3021 <p><label>Your username: <input type="text" name="username" maxlength="10" /></label></p> |
|
3022 <p><label>Password: <input type="password" name="password1" /></label></p> |
|
3023 <p><label>Password (again): <input type="password" name="password2" /></label></p> |
|
3024 <input type="submit" /> |
|
3025 </form> |
|
3026 >>> print t.render(Context({'form': UserRegistration({'username': 'django'}, auto_id=False)})) |
|
3027 <form action=""> |
|
3028 <p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> |
|
3029 <ul class="errorlist"><li>This field is required.</li></ul><p><label>Password: <input type="password" name="password1" /></label></p> |
|
3030 <ul class="errorlist"><li>This field is required.</li></ul><p><label>Password (again): <input type="password" name="password2" /></label></p> |
|
3031 <input type="submit" /> |
|
3032 </form> |
|
3033 |
|
3034 Use form.[field].label to output a field's label. You can specify the label for |
|
3035 a field by using the 'label' argument to a Field class. If you don't specify |
|
3036 'label', Django will use the field name with underscores converted to spaces, |
|
3037 and the initial letter capitalized. |
|
3038 >>> t = Template('''<form action=""> |
|
3039 ... <p><label>{{ form.username.label }}: {{ form.username }}</label></p> |
|
3040 ... <p><label>{{ form.password1.label }}: {{ form.password1 }}</label></p> |
|
3041 ... <p><label>{{ form.password2.label }}: {{ form.password2 }}</label></p> |
|
3042 ... <input type="submit" /> |
|
3043 ... </form>''') |
|
3044 >>> print t.render(Context({'form': UserRegistration(auto_id=False)})) |
|
3045 <form action=""> |
|
3046 <p><label>Username: <input type="text" name="username" maxlength="10" /></label></p> |
|
3047 <p><label>Password1: <input type="password" name="password1" /></label></p> |
|
3048 <p><label>Password2: <input type="password" name="password2" /></label></p> |
|
3049 <input type="submit" /> |
|
3050 </form> |
|
3051 |
|
3052 User form.[field].label_tag to output a field's label with a <label> tag |
|
3053 wrapped around it, but *only* if the given field has an "id" attribute. |
|
3054 Recall from above that passing the "auto_id" argument to a Form gives each |
|
3055 field an "id" attribute. |
|
3056 >>> t = Template('''<form action=""> |
|
3057 ... <p>{{ form.username.label_tag }}: {{ form.username }}</p> |
|
3058 ... <p>{{ form.password1.label_tag }}: {{ form.password1 }}</p> |
|
3059 ... <p>{{ form.password2.label_tag }}: {{ form.password2 }}</p> |
|
3060 ... <input type="submit" /> |
|
3061 ... </form>''') |
|
3062 >>> print t.render(Context({'form': UserRegistration(auto_id=False)})) |
|
3063 <form action=""> |
|
3064 <p>Username: <input type="text" name="username" maxlength="10" /></p> |
|
3065 <p>Password1: <input type="password" name="password1" /></p> |
|
3066 <p>Password2: <input type="password" name="password2" /></p> |
|
3067 <input type="submit" /> |
|
3068 </form> |
|
3069 >>> print t.render(Context({'form': UserRegistration(auto_id='id_%s')})) |
|
3070 <form action=""> |
|
3071 <p><label for="id_username">Username</label>: <input id="id_username" type="text" name="username" maxlength="10" /></p> |
|
3072 <p><label for="id_password1">Password1</label>: <input type="password" name="password1" id="id_password1" /></p> |
|
3073 <p><label for="id_password2">Password2</label>: <input type="password" name="password2" id="id_password2" /></p> |
|
3074 <input type="submit" /> |
|
3075 </form> |
|
3076 |
|
3077 User form.[field].help_text to output a field's help text. If the given field |
|
3078 does not have help text, nothing will be output. |
|
3079 >>> t = Template('''<form action=""> |
|
3080 ... <p>{{ form.username.label_tag }}: {{ form.username }}<br />{{ form.username.help_text }}</p> |
|
3081 ... <p>{{ form.password1.label_tag }}: {{ form.password1 }}</p> |
|
3082 ... <p>{{ form.password2.label_tag }}: {{ form.password2 }}</p> |
|
3083 ... <input type="submit" /> |
|
3084 ... </form>''') |
|
3085 >>> print t.render(Context({'form': UserRegistration(auto_id=False)})) |
|
3086 <form action=""> |
|
3087 <p>Username: <input type="text" name="username" maxlength="10" /><br />Good luck picking a username that doesn't already exist.</p> |
|
3088 <p>Password1: <input type="password" name="password1" /></p> |
|
3089 <p>Password2: <input type="password" name="password2" /></p> |
|
3090 <input type="submit" /> |
|
3091 </form> |
|
3092 >>> Template('{{ form.password1.help_text }}').render(Context({'form': UserRegistration(auto_id=False)})) |
|
3093 '' |
|
3094 |
|
3095 The label_tag() method takes an optional attrs argument: a dictionary of HTML |
|
3096 attributes to add to the <label> tag. |
|
3097 >>> f = UserRegistration(auto_id='id_%s') |
|
3098 >>> for bf in f: |
|
3099 ... print bf.label_tag(attrs={'class': 'pretty'}) |
|
3100 <label for="id_username" class="pretty">Username</label> |
|
3101 <label for="id_password1" class="pretty">Password1</label> |
|
3102 <label for="id_password2" class="pretty">Password2</label> |
|
3103 |
|
3104 To display the errors that aren't associated with a particular field -- e.g., |
|
3105 the errors caused by Form.clean() -- use {{ form.non_field_errors }} in the |
|
3106 template. If used on its own, it is displayed as a <ul> (or an empty string, if |
|
3107 the list of errors is empty). You can also use it in {% if %} statements. |
|
3108 >>> t = Template('''<form action=""> |
|
3109 ... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> |
|
3110 ... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> |
|
3111 ... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> |
|
3112 ... <input type="submit" /> |
|
3113 ... </form>''') |
|
3114 >>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)})) |
|
3115 <form action=""> |
|
3116 <p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> |
|
3117 <p><label>Password: <input type="password" name="password1" value="foo" /></label></p> |
|
3118 <p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> |
|
3119 <input type="submit" /> |
|
3120 </form> |
|
3121 >>> t = Template('''<form action=""> |
|
3122 ... {{ form.non_field_errors }} |
|
3123 ... {{ form.username.errors.as_ul }}<p><label>Your username: {{ form.username }}</label></p> |
|
3124 ... {{ form.password1.errors.as_ul }}<p><label>Password: {{ form.password1 }}</label></p> |
|
3125 ... {{ form.password2.errors.as_ul }}<p><label>Password (again): {{ form.password2 }}</label></p> |
|
3126 ... <input type="submit" /> |
|
3127 ... </form>''') |
|
3128 >>> print t.render(Context({'form': UserRegistration({'username': 'django', 'password1': 'foo', 'password2': 'bar'}, auto_id=False)})) |
|
3129 <form action=""> |
|
3130 <ul class="errorlist"><li>Please make sure your passwords match.</li></ul> |
|
3131 <p><label>Your username: <input type="text" name="username" value="django" maxlength="10" /></label></p> |
|
3132 <p><label>Password: <input type="password" name="password1" value="foo" /></label></p> |
|
3133 <p><label>Password (again): <input type="password" name="password2" value="bar" /></label></p> |
|
3134 <input type="submit" /> |
|
3135 </form> |
|
3136 |
|
3137 ############### |
|
3138 # Extra stuff # |
|
3139 ############### |
|
3140 |
|
3141 The newforms library comes with some extra, higher-level Field and Widget |
|
3142 classes that demonstrate some of the library's abilities. |
|
3143 |
|
3144 # SelectDateWidget ############################################################ |
|
3145 |
|
3146 >>> from django.newforms.extras import SelectDateWidget |
|
3147 >>> w = SelectDateWidget(years=('2007','2008','2009','2010','2011','2012','2013','2014','2015','2016')) |
|
3148 >>> print w.render('mydate', '') |
|
3149 <select name="mydate_month"> |
|
3150 <option value="1">January</option> |
|
3151 <option value="2">February</option> |
|
3152 <option value="3">March</option> |
|
3153 <option value="4">April</option> |
|
3154 <option value="5">May</option> |
|
3155 <option value="6">June</option> |
|
3156 <option value="7">July</option> |
|
3157 <option value="8">August</option> |
|
3158 <option value="9">September</option> |
|
3159 <option value="10">October</option> |
|
3160 <option value="11">November</option> |
|
3161 <option value="12">December</option> |
|
3162 </select> |
|
3163 <select name="mydate_day"> |
|
3164 <option value="1">1</option> |
|
3165 <option value="2">2</option> |
|
3166 <option value="3">3</option> |
|
3167 <option value="4">4</option> |
|
3168 <option value="5">5</option> |
|
3169 <option value="6">6</option> |
|
3170 <option value="7">7</option> |
|
3171 <option value="8">8</option> |
|
3172 <option value="9">9</option> |
|
3173 <option value="10">10</option> |
|
3174 <option value="11">11</option> |
|
3175 <option value="12">12</option> |
|
3176 <option value="13">13</option> |
|
3177 <option value="14">14</option> |
|
3178 <option value="15">15</option> |
|
3179 <option value="16">16</option> |
|
3180 <option value="17">17</option> |
|
3181 <option value="18">18</option> |
|
3182 <option value="19">19</option> |
|
3183 <option value="20">20</option> |
|
3184 <option value="21">21</option> |
|
3185 <option value="22">22</option> |
|
3186 <option value="23">23</option> |
|
3187 <option value="24">24</option> |
|
3188 <option value="25">25</option> |
|
3189 <option value="26">26</option> |
|
3190 <option value="27">27</option> |
|
3191 <option value="28">28</option> |
|
3192 <option value="29">29</option> |
|
3193 <option value="30">30</option> |
|
3194 <option value="31">31</option> |
|
3195 </select> |
|
3196 <select name="mydate_year"> |
|
3197 <option value="2007">2007</option> |
|
3198 <option value="2008">2008</option> |
|
3199 <option value="2009">2009</option> |
|
3200 <option value="2010">2010</option> |
|
3201 <option value="2011">2011</option> |
|
3202 <option value="2012">2012</option> |
|
3203 <option value="2013">2013</option> |
|
3204 <option value="2014">2014</option> |
|
3205 <option value="2015">2015</option> |
|
3206 <option value="2016">2016</option> |
|
3207 </select> |
|
3208 >>> w.render('mydate', None) == w.render('mydate', '') |
|
3209 True |
|
3210 >>> print w.render('mydate', '2010-04-15') |
|
3211 <select name="mydate_month"> |
|
3212 <option value="1">January</option> |
|
3213 <option value="2">February</option> |
|
3214 <option value="3">March</option> |
|
3215 <option value="4" selected="selected">April</option> |
|
3216 <option value="5">May</option> |
|
3217 <option value="6">June</option> |
|
3218 <option value="7">July</option> |
|
3219 <option value="8">August</option> |
|
3220 <option value="9">September</option> |
|
3221 <option value="10">October</option> |
|
3222 <option value="11">November</option> |
|
3223 <option value="12">December</option> |
|
3224 </select> |
|
3225 <select name="mydate_day"> |
|
3226 <option value="1">1</option> |
|
3227 <option value="2">2</option> |
|
3228 <option value="3">3</option> |
|
3229 <option value="4">4</option> |
|
3230 <option value="5">5</option> |
|
3231 <option value="6">6</option> |
|
3232 <option value="7">7</option> |
|
3233 <option value="8">8</option> |
|
3234 <option value="9">9</option> |
|
3235 <option value="10">10</option> |
|
3236 <option value="11">11</option> |
|
3237 <option value="12">12</option> |
|
3238 <option value="13">13</option> |
|
3239 <option value="14">14</option> |
|
3240 <option value="15" selected="selected">15</option> |
|
3241 <option value="16">16</option> |
|
3242 <option value="17">17</option> |
|
3243 <option value="18">18</option> |
|
3244 <option value="19">19</option> |
|
3245 <option value="20">20</option> |
|
3246 <option value="21">21</option> |
|
3247 <option value="22">22</option> |
|
3248 <option value="23">23</option> |
|
3249 <option value="24">24</option> |
|
3250 <option value="25">25</option> |
|
3251 <option value="26">26</option> |
|
3252 <option value="27">27</option> |
|
3253 <option value="28">28</option> |
|
3254 <option value="29">29</option> |
|
3255 <option value="30">30</option> |
|
3256 <option value="31">31</option> |
|
3257 </select> |
|
3258 <select name="mydate_year"> |
|
3259 <option value="2007">2007</option> |
|
3260 <option value="2008">2008</option> |
|
3261 <option value="2009">2009</option> |
|
3262 <option value="2010" selected="selected">2010</option> |
|
3263 <option value="2011">2011</option> |
|
3264 <option value="2012">2012</option> |
|
3265 <option value="2013">2013</option> |
|
3266 <option value="2014">2014</option> |
|
3267 <option value="2015">2015</option> |
|
3268 <option value="2016">2016</option> |
|
3269 </select> |
|
3270 |
|
3271 # USZipCodeField ############################################################## |
|
3272 |
|
3273 USZipCodeField validates that the data is either a five-digit U.S. zip code or |
|
3274 a zip+4. |
|
3275 >>> from django.contrib.localflavor.usa.forms import USZipCodeField |
|
3276 >>> f = USZipCodeField() |
|
3277 >>> f.clean('60606') |
|
3278 u'60606' |
|
3279 >>> f.clean(60606) |
|
3280 u'60606' |
|
3281 >>> f.clean('04000') |
|
3282 u'04000' |
|
3283 >>> f.clean('4000') |
|
3284 Traceback (most recent call last): |
|
3285 ... |
|
3286 ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] |
|
3287 >>> f.clean('60606-1234') |
|
3288 u'60606-1234' |
|
3289 >>> f.clean('6060-1234') |
|
3290 Traceback (most recent call last): |
|
3291 ... |
|
3292 ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] |
|
3293 >>> f.clean('60606-') |
|
3294 Traceback (most recent call last): |
|
3295 ... |
|
3296 ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] |
|
3297 >>> f.clean(None) |
|
3298 Traceback (most recent call last): |
|
3299 ... |
|
3300 ValidationError: [u'This field is required.'] |
|
3301 >>> f.clean('') |
|
3302 Traceback (most recent call last): |
|
3303 ... |
|
3304 ValidationError: [u'This field is required.'] |
|
3305 |
|
3306 >>> f = USZipCodeField(required=False) |
|
3307 >>> f.clean('60606') |
|
3308 u'60606' |
|
3309 >>> f.clean(60606) |
|
3310 u'60606' |
|
3311 >>> f.clean('04000') |
|
3312 u'04000' |
|
3313 >>> f.clean('4000') |
|
3314 Traceback (most recent call last): |
|
3315 ... |
|
3316 ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] |
|
3317 >>> f.clean('60606-1234') |
|
3318 u'60606-1234' |
|
3319 >>> f.clean('6060-1234') |
|
3320 Traceback (most recent call last): |
|
3321 ... |
|
3322 ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] |
|
3323 >>> f.clean('60606-') |
|
3324 Traceback (most recent call last): |
|
3325 ... |
|
3326 ValidationError: [u'Enter a zip code in the format XXXXX or XXXXX-XXXX.'] |
|
3327 >>> f.clean(None) |
|
3328 u'' |
|
3329 >>> f.clean('') |
|
3330 u'' |
|
3331 |
|
3332 # USPhoneNumberField ########################################################## |
|
3333 |
|
3334 USPhoneNumberField validates that the data is a valid U.S. phone number, |
|
3335 including the area code. It's normalized to XXX-XXX-XXXX format. |
|
3336 >>> from django.contrib.localflavor.usa.forms import USPhoneNumberField |
|
3337 >>> f = USPhoneNumberField() |
|
3338 >>> f.clean('312-555-1212') |
|
3339 u'312-555-1212' |
|
3340 >>> f.clean('3125551212') |
|
3341 u'312-555-1212' |
|
3342 >>> f.clean('312 555-1212') |
|
3343 u'312-555-1212' |
|
3344 >>> f.clean('(312) 555-1212') |
|
3345 u'312-555-1212' |
|
3346 >>> f.clean('312 555 1212') |
|
3347 u'312-555-1212' |
|
3348 >>> f.clean('312.555.1212') |
|
3349 u'312-555-1212' |
|
3350 >>> f.clean('312.555-1212') |
|
3351 u'312-555-1212' |
|
3352 >>> f.clean(' (312) 555.1212 ') |
|
3353 u'312-555-1212' |
|
3354 >>> f.clean('555-1212') |
|
3355 Traceback (most recent call last): |
|
3356 ... |
|
3357 ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] |
|
3358 >>> f.clean('312-55-1212') |
|
3359 Traceback (most recent call last): |
|
3360 ... |
|
3361 ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] |
|
3362 >>> f.clean(None) |
|
3363 Traceback (most recent call last): |
|
3364 ... |
|
3365 ValidationError: [u'This field is required.'] |
|
3366 >>> f.clean('') |
|
3367 Traceback (most recent call last): |
|
3368 ... |
|
3369 ValidationError: [u'This field is required.'] |
|
3370 |
|
3371 >>> f = USPhoneNumberField(required=False) |
|
3372 >>> f.clean('312-555-1212') |
|
3373 u'312-555-1212' |
|
3374 >>> f.clean('3125551212') |
|
3375 u'312-555-1212' |
|
3376 >>> f.clean('312 555-1212') |
|
3377 u'312-555-1212' |
|
3378 >>> f.clean('(312) 555-1212') |
|
3379 u'312-555-1212' |
|
3380 >>> f.clean('312 555 1212') |
|
3381 u'312-555-1212' |
|
3382 >>> f.clean('312.555.1212') |
|
3383 u'312-555-1212' |
|
3384 >>> f.clean('312.555-1212') |
|
3385 u'312-555-1212' |
|
3386 >>> f.clean(' (312) 555.1212 ') |
|
3387 u'312-555-1212' |
|
3388 >>> f.clean('555-1212') |
|
3389 Traceback (most recent call last): |
|
3390 ... |
|
3391 ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] |
|
3392 >>> f.clean('312-55-1212') |
|
3393 Traceback (most recent call last): |
|
3394 ... |
|
3395 ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] |
|
3396 >>> f.clean(None) |
|
3397 u'' |
|
3398 >>> f.clean('') |
|
3399 u'' |
|
3400 |
|
3401 # USStateField ################################################################ |
|
3402 |
|
3403 USStateField validates that the data is either an abbreviation or name of a |
|
3404 U.S. state. |
|
3405 >>> from django.contrib.localflavor.usa.forms import USStateField |
|
3406 >>> f = USStateField() |
|
3407 >>> f.clean('il') |
|
3408 u'IL' |
|
3409 >>> f.clean('IL') |
|
3410 u'IL' |
|
3411 >>> f.clean('illinois') |
|
3412 u'IL' |
|
3413 >>> f.clean(' illinois ') |
|
3414 u'IL' |
|
3415 >>> f.clean(60606) |
|
3416 Traceback (most recent call last): |
|
3417 ... |
|
3418 ValidationError: [u'Enter a U.S. state or territory.'] |
|
3419 >>> f.clean(None) |
|
3420 Traceback (most recent call last): |
|
3421 ... |
|
3422 ValidationError: [u'This field is required.'] |
|
3423 >>> f.clean('') |
|
3424 Traceback (most recent call last): |
|
3425 ... |
|
3426 ValidationError: [u'This field is required.'] |
|
3427 |
|
3428 >>> f = USStateField(required=False) |
|
3429 >>> f.clean('il') |
|
3430 u'IL' |
|
3431 >>> f.clean('IL') |
|
3432 u'IL' |
|
3433 >>> f.clean('illinois') |
|
3434 u'IL' |
|
3435 >>> f.clean(' illinois ') |
|
3436 u'IL' |
|
3437 >>> f.clean(60606) |
|
3438 Traceback (most recent call last): |
|
3439 ... |
|
3440 ValidationError: [u'Enter a U.S. state or territory.'] |
|
3441 >>> f.clean(None) |
|
3442 u'' |
|
3443 >>> f.clean('') |
|
3444 u'' |
|
3445 |
|
3446 # USStateSelect ############################################################### |
|
3447 |
|
3448 USStateSelect is a Select widget that uses a list of U.S. states/territories |
|
3449 as its choices. |
|
3450 >>> from django.contrib.localflavor.usa.forms import USStateSelect |
|
3451 >>> w = USStateSelect() |
|
3452 >>> print w.render('state', 'IL') |
|
3453 <select name="state"> |
|
3454 <option value="AL">Alabama</option> |
|
3455 <option value="AK">Alaska</option> |
|
3456 <option value="AS">American Samoa</option> |
|
3457 <option value="AZ">Arizona</option> |
|
3458 <option value="AR">Arkansas</option> |
|
3459 <option value="CA">California</option> |
|
3460 <option value="CO">Colorado</option> |
|
3461 <option value="CT">Connecticut</option> |
|
3462 <option value="DE">Deleware</option> |
|
3463 <option value="DC">District of Columbia</option> |
|
3464 <option value="FM">Federated States of Micronesia</option> |
|
3465 <option value="FL">Florida</option> |
|
3466 <option value="GA">Georgia</option> |
|
3467 <option value="GU">Guam</option> |
|
3468 <option value="HI">Hawaii</option> |
|
3469 <option value="ID">Idaho</option> |
|
3470 <option value="IL" selected="selected">Illinois</option> |
|
3471 <option value="IN">Indiana</option> |
|
3472 <option value="IA">Iowa</option> |
|
3473 <option value="KS">Kansas</option> |
|
3474 <option value="KY">Kentucky</option> |
|
3475 <option value="LA">Louisiana</option> |
|
3476 <option value="ME">Maine</option> |
|
3477 <option value="MH">Marshall Islands</option> |
|
3478 <option value="MD">Maryland</option> |
|
3479 <option value="MA">Massachusetts</option> |
|
3480 <option value="MI">Michigan</option> |
|
3481 <option value="MN">Minnesota</option> |
|
3482 <option value="MS">Mississippi</option> |
|
3483 <option value="MO">Missouri</option> |
|
3484 <option value="MT">Montana</option> |
|
3485 <option value="NE">Nebraska</option> |
|
3486 <option value="NV">Nevada</option> |
|
3487 <option value="NH">New Hampshire</option> |
|
3488 <option value="NJ">New Jersey</option> |
|
3489 <option value="NM">New Mexico</option> |
|
3490 <option value="NY">New York</option> |
|
3491 <option value="NC">North Carolina</option> |
|
3492 <option value="ND">North Dakota</option> |
|
3493 <option value="MP">Northern Mariana Islands</option> |
|
3494 <option value="OH">Ohio</option> |
|
3495 <option value="OK">Oklahoma</option> |
|
3496 <option value="OR">Oregon</option> |
|
3497 <option value="PW">Palau</option> |
|
3498 <option value="PA">Pennsylvania</option> |
|
3499 <option value="PR">Puerto Rico</option> |
|
3500 <option value="RI">Rhode Island</option> |
|
3501 <option value="SC">South Carolina</option> |
|
3502 <option value="SD">South Dakota</option> |
|
3503 <option value="TN">Tennessee</option> |
|
3504 <option value="TX">Texas</option> |
|
3505 <option value="UT">Utah</option> |
|
3506 <option value="VT">Vermont</option> |
|
3507 <option value="VI">Virgin Islands</option> |
|
3508 <option value="VA">Virginia</option> |
|
3509 <option value="WA">Washington</option> |
|
3510 <option value="WV">West Virginia</option> |
|
3511 <option value="WI">Wisconsin</option> |
|
3512 <option value="WY">Wyoming</option> |
|
3513 </select> |
|
3514 |
|
3515 # UKPostcodeField ############################################################# |
|
3516 |
|
3517 UKPostcodeField validates that the data is a valid UK postcode. |
|
3518 >>> from django.contrib.localflavor.uk.forms import UKPostcodeField |
|
3519 >>> f = UKPostcodeField() |
|
3520 >>> f.clean('BT32 4PX') |
|
3521 u'BT32 4PX' |
|
3522 >>> f.clean('GIR 0AA') |
|
3523 u'GIR 0AA' |
|
3524 >>> f.clean('BT324PX') |
|
3525 Traceback (most recent call last): |
|
3526 ... |
|
3527 ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] |
|
3528 >>> f.clean('1NV 4L1D') |
|
3529 Traceback (most recent call last): |
|
3530 ... |
|
3531 ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] |
|
3532 >>> f.clean(None) |
|
3533 Traceback (most recent call last): |
|
3534 ... |
|
3535 ValidationError: [u'This field is required.'] |
|
3536 >>> f.clean('') |
|
3537 Traceback (most recent call last): |
|
3538 ... |
|
3539 ValidationError: [u'This field is required.'] |
|
3540 |
|
3541 >>> f = UKPostcodeField(required=False) |
|
3542 >>> f.clean('BT32 4PX') |
|
3543 u'BT32 4PX' |
|
3544 >>> f.clean('GIR 0AA') |
|
3545 u'GIR 0AA' |
|
3546 >>> f.clean('1NV 4L1D') |
|
3547 Traceback (most recent call last): |
|
3548 ... |
|
3549 ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] |
|
3550 >>> f.clean('BT324PX') |
|
3551 Traceback (most recent call last): |
|
3552 ... |
|
3553 ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.'] |
|
3554 >>> f.clean(None) |
|
3555 u'' |
|
3556 >>> f.clean('') |
|
3557 u'' |
|
3558 |
|
3559 ################################# |
|
3560 # Tests of underlying functions # |
|
3561 ################################# |
|
3562 |
|
3563 # smart_unicode tests |
|
3564 >>> from django.newforms.util import smart_unicode |
|
3565 >>> class Test: |
|
3566 ... def __str__(self): |
|
3567 ... return 'ŠĐĆŽćžšđ' |
|
3568 >>> class TestU: |
|
3569 ... def __str__(self): |
|
3570 ... return 'Foo' |
|
3571 ... def __unicode__(self): |
|
3572 ... return u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111' |
|
3573 >>> smart_unicode(Test()) |
|
3574 u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111' |
|
3575 >>> smart_unicode(TestU()) |
|
3576 u'\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111' |
|
3577 >>> smart_unicode(1) |
|
3578 u'1' |
|
3579 >>> smart_unicode('foo') |
|
3580 u'foo' |
|
3581 """ |
|
3582 |
|
3583 if __name__ == "__main__": |
|
3584 import doctest |
|
3585 doctest.testmod() |
|