~ubuntu-branches/ubuntu/saucy/python-django/saucy-updates

« back to all changes in this revision

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

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2009-07-29 11:26:28 UTC
  • mfrom: (1.2.3 upstream)
  • mto: This revision was merged to the branch mainline in revision 22.
  • Revision ID: james.westby@ubuntu.com-20090729112628-9qrzwnl9x32jxhbg
Tags: upstream-1.1
Import upstream version 1.1

Show diffs side-by-side

added added

removed removed

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