5 from django
.utils
.translation
import gettext
6 from util
import ErrorList
, ValidationError
, smart_unicode
7 from widgets
import TextInput
, PasswordInput
, HiddenInput
, MultipleHiddenInput
, CheckboxInput
, Select
, NullBooleanSelect
, SelectMultiple
13 'Field', 'CharField', 'IntegerField',
14 'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
15 'DEFAULT_TIME_INPUT_FORMATS', 'TimeField',
16 'DEFAULT_DATETIME_INPUT_FORMATS', 'DateTimeField',
17 'RegexField', 'EmailField', 'URLField', 'BooleanField',
18 'ChoiceField', 'NullBooleanField', 'MultipleChoiceField',
19 'ComboField', 'MultiValueField',
23 # These values, if given to to_python(), will trigger the self.required check.
24 EMPTY_VALUES
= (None, '')
27 set # Only available in Python 2.4+
29 from sets
import Set
as set # Python 2.3 fallback
32 widget
= TextInput
# Default widget to use when rendering this type of Field.
33 hidden_widget
= HiddenInput
# Default widget to use when rendering this as "hidden".
35 # Tracks each time a Field instance is created. Used to retain order.
38 def __init__(self
, required
=True, widget
=None, label
=None, initial
=None, help_text
=None):
39 # required -- Boolean that specifies whether the field is required.
41 # widget -- A Widget class, or instance of a Widget class, that should be
42 # used for this Field when displaying it. Each Field has a default
43 # Widget that it'll use if you don't specify this. In most cases,
44 # the default widget is TextInput.
45 # label -- A verbose name for this field, for use in displaying this field in
46 # a form. By default, Django will use a "pretty" version of the form
47 # field name, if the Field is part of a Form.
48 # initial -- A value to use in this Field's initial display. This value is
49 # *not* used as a fallback if data isn't given.
50 # help_text -- An optional string to use as "help text" for this Field.
52 label
= smart_unicode(label
)
53 self
.required
, self
.label
, self
.initial
= required
, label
, initial
54 self
.help_text
= smart_unicode(help_text
or '')
55 widget
= widget
or self
.widget
56 if isinstance(widget
, type):
59 # Hook into self.widget_attrs() for any Field-specific HTML attributes.
60 extra_attrs
= self
.widget_attrs(widget
)
62 widget
.attrs
.update(extra_attrs
)
66 # Increase the creation counter, and save our local copy.
67 self
.creation_counter
= Field
.creation_counter
68 Field
.creation_counter
+= 1
70 def clean(self
, value
):
72 Validates the given value and returns its "cleaned" value as an
73 appropriate Python object.
75 Raises ValidationError for any errors.
77 if self
.required
and value
in EMPTY_VALUES
:
78 raise ValidationError(gettext(u
'This field is required.'))
81 def widget_attrs(self
, widget
):
83 Given a Widget instance (*not* a Widget class), returns a dictionary of
84 any HTML attributes that should be added to the Widget, based on this
89 class CharField(Field
):
90 def __init__(self
, max_length
=None, min_length
=None, *args
, **kwargs
):
91 self
.max_length
, self
.min_length
= max_length
, min_length
92 super(CharField
, self
).__init
__(*args
, **kwargs
)
94 def clean(self
, value
):
95 "Validates max_length and min_length. Returns a Unicode object."
96 super(CharField
, self
).clean(value
)
97 if value
in EMPTY_VALUES
:
99 value
= smart_unicode(value
)
100 if self
.max_length
is not None and len(value
) > self
.max_length
:
101 raise ValidationError(gettext(u
'Ensure this value has at most %d characters.') % self
.max_length
)
102 if self
.min_length
is not None and len(value
) < self
.min_length
:
103 raise ValidationError(gettext(u
'Ensure this value has at least %d characters.') % self
.min_length
)
106 def widget_attrs(self
, widget
):
107 if self
.max_length
is not None and isinstance(widget
, (TextInput
, PasswordInput
)):
108 return {'maxlength': str(self
.max_length
)}
110 class IntegerField(Field
):
111 def __init__(self
, max_value
=None, min_value
=None, *args
, **kwargs
):
112 self
.max_value
, self
.min_value
= max_value
, min_value
113 super(IntegerField
, self
).__init
__(*args
, **kwargs
)
115 def clean(self
, value
):
117 Validates that int() can be called on the input. Returns the result
118 of int(). Returns None for empty values.
120 super(IntegerField
, self
).clean(value
)
121 if value
in EMPTY_VALUES
:
125 except (ValueError, TypeError):
126 raise ValidationError(gettext(u
'Enter a whole number.'))
127 if self
.max_value
is not None and value
> self
.max_value
:
128 raise ValidationError(gettext(u
'Ensure this value is less than or equal to %s.') % self
.max_value
)
129 if self
.min_value
is not None and value
< self
.min_value
:
130 raise ValidationError(gettext(u
'Ensure this value is greater than or equal to %s.') % self
.min_value
)
133 DEFAULT_DATE_INPUT_FORMATS
= (
134 '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
135 '%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
136 '%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006'
137 '%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006'
138 '%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006'
141 class DateField(Field
):
142 def __init__(self
, input_formats
=None, *args
, **kwargs
):
143 super(DateField
, self
).__init
__(*args
, **kwargs
)
144 self
.input_formats
= input_formats
or DEFAULT_DATE_INPUT_FORMATS
146 def clean(self
, value
):
148 Validates that the input can be converted to a date. Returns a Python
149 datetime.date object.
151 super(DateField
, self
).clean(value
)
152 if value
in EMPTY_VALUES
:
154 if isinstance(value
, datetime
.datetime
):
156 if isinstance(value
, datetime
.date
):
158 for format
in self
.input_formats
:
160 return datetime
.date(*time
.strptime(value
, format
)[:3])
163 raise ValidationError(gettext(u
'Enter a valid date.'))
165 DEFAULT_TIME_INPUT_FORMATS
= (
166 '%H:%M:%S', # '14:30:59'
170 class TimeField(Field
):
171 def __init__(self
, input_formats
=None, *args
, **kwargs
):
172 super(TimeField
, self
).__init
__(*args
, **kwargs
)
173 self
.input_formats
= input_formats
or DEFAULT_TIME_INPUT_FORMATS
175 def clean(self
, value
):
177 Validates that the input can be converted to a time. Returns a Python
178 datetime.time object.
180 super(TimeField
, self
).clean(value
)
181 if value
in EMPTY_VALUES
:
183 if isinstance(value
, datetime
.time
):
185 for format
in self
.input_formats
:
187 return datetime
.time(*time
.strptime(value
, format
)[3:6])
190 raise ValidationError(gettext(u
'Enter a valid time.'))
192 DEFAULT_DATETIME_INPUT_FORMATS
= (
193 '%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
194 '%Y-%m-%d %H:%M', # '2006-10-25 14:30'
195 '%Y-%m-%d', # '2006-10-25'
196 '%m/%d/%Y %H:%M:%S', # '10/25/2006 14:30:59'
197 '%m/%d/%Y %H:%M', # '10/25/2006 14:30'
198 '%m/%d/%Y', # '10/25/2006'
199 '%m/%d/%y %H:%M:%S', # '10/25/06 14:30:59'
200 '%m/%d/%y %H:%M', # '10/25/06 14:30'
201 '%m/%d/%y', # '10/25/06'
204 class DateTimeField(Field
):
205 def __init__(self
, input_formats
=None, *args
, **kwargs
):
206 super(DateTimeField
, self
).__init
__(*args
, **kwargs
)
207 self
.input_formats
= input_formats
or DEFAULT_DATETIME_INPUT_FORMATS
209 def clean(self
, value
):
211 Validates that the input can be converted to a datetime. Returns a
212 Python datetime.datetime object.
214 super(DateTimeField
, self
).clean(value
)
215 if value
in EMPTY_VALUES
:
217 if isinstance(value
, datetime
.datetime
):
219 if isinstance(value
, datetime
.date
):
220 return datetime
.datetime(value
.year
, value
.month
, value
.day
)
221 for format
in self
.input_formats
:
223 return datetime
.datetime(*time
.strptime(value
, format
)[:6])
226 raise ValidationError(gettext(u
'Enter a valid date/time.'))
228 class RegexField(Field
):
229 def __init__(self
, regex
, max_length
=None, min_length
=None, error_message
=None, *args
, **kwargs
):
231 regex can be either a string or a compiled regular expression object.
232 error_message is an optional error message to use, if
233 'Enter a valid value' is too generic for you.
235 super(RegexField
, self
).__init
__(*args
, **kwargs
)
236 if isinstance(regex
, basestring
):
237 regex
= re
.compile(regex
)
239 self
.max_length
, self
.min_length
= max_length
, min_length
240 self
.error_message
= error_message
or gettext(u
'Enter a valid value.')
242 def clean(self
, value
):
244 Validates that the input matches the regular expression. Returns a
247 super(RegexField
, self
).clean(value
)
248 if value
in EMPTY_VALUES
:
250 value
= smart_unicode(value
)
253 if self
.max_length
is not None and len(value
) > self
.max_length
:
254 raise ValidationError(gettext(u
'Ensure this value has at most %d characters.') % self
.max_length
)
255 if self
.min_length
is not None and len(value
) < self
.min_length
:
256 raise ValidationError(gettext(u
'Ensure this value has at least %d characters.') % self
.min_length
)
257 if not self
.regex
.search(value
):
258 raise ValidationError(self
.error_message
)
261 email_re
= re
.compile(
262 r
"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*" # dot-atom
263 r
'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
264 r
')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re
.IGNORECASE
) # domain
266 class EmailField(RegexField
):
267 def __init__(self
, max_length
=None, min_length
=None, *args
, **kwargs
):
268 RegexField
.__init
__(self
, email_re
, max_length
, min_length
,
269 gettext(u
'Enter a valid e-mail address.'), *args
, **kwargs
)
272 r
'^https?://' # http:// or https://
273 r
'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|' #domain...
274 r
'localhost|' #localhost...
275 r
'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
276 r
'(?::\d+)?' # optional port
277 r
'(?:/?|/\S+)$', re
.IGNORECASE
)
280 from django
.conf
import settings
281 URL_VALIDATOR_USER_AGENT
= settings
.URL_VALIDATOR_USER_AGENT
283 # It's OK if Django settings aren't configured.
284 URL_VALIDATOR_USER_AGENT
= 'Django (http://www.djangoproject.com/)'
286 class URLField(RegexField
):
287 def __init__(self
, max_length
=None, min_length
=None, verify_exists
=False,
288 validator_user_agent
=URL_VALIDATOR_USER_AGENT
, *args
, **kwargs
):
289 super(URLField
, self
).__init
__(url_re
, max_length
, min_length
, gettext(u
'Enter a valid URL.'), *args
, **kwargs
)
290 self
.verify_exists
= verify_exists
291 self
.user_agent
= validator_user_agent
293 def clean(self
, value
):
294 value
= super(URLField
, self
).clean(value
)
297 if self
.verify_exists
:
299 from django
.conf
import settings
301 "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
302 "Accept-Language": "en-us,en;q=0.5",
303 "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
304 "Connection": "close",
305 "User-Agent": self
.user_agent
,
308 req
= urllib2
.Request(value
, None, headers
)
309 u
= urllib2
.urlopen(req
)
311 raise ValidationError(gettext(u
'Enter a valid URL.'))
312 except: # urllib2.URLError, httplib.InvalidURL, etc.
313 raise ValidationError(gettext(u
'This URL appears to be a broken link.'))
316 class BooleanField(Field
):
317 widget
= CheckboxInput
319 def clean(self
, value
):
320 "Returns a Python boolean object."
321 super(BooleanField
, self
).clean(value
)
324 class NullBooleanField(BooleanField
):
326 A field whose valid values are None, True and False. Invalid values are
329 widget
= NullBooleanSelect
331 def clean(self
, value
):
332 return {True: True, False: False}.get(value
, None)
334 class ChoiceField(Field
):
335 def __init__(self
, choices
=(), required
=True, widget
=Select
, label
=None, initial
=None, help_text
=None):
336 super(ChoiceField
, self
).__init
__(required
, widget
, label
, initial
, help_text
)
337 self
.choices
= choices
339 def _get_choices(self
):
342 def _set_choices(self
, value
):
343 # Setting choices also sets the choices on the widget.
344 # choices can be any iterable, but we call list() on it because
345 # it will be consumed more than once.
346 self
._choices
= self
.widget
.choices
= list(value
)
348 choices
= property(_get_choices
, _set_choices
)
350 def clean(self
, value
):
352 Validates that the input is in self.choices.
354 value
= super(ChoiceField
, self
).clean(value
)
355 if value
in EMPTY_VALUES
:
357 value
= smart_unicode(value
)
360 valid_values
= set([str(k
) for k
, v
in self
.choices
])
361 if value
not in valid_values
:
362 raise ValidationError(gettext(u
'Select a valid choice. That choice is not one of the available choices.'))
365 class MultipleChoiceField(ChoiceField
):
366 hidden_widget
= MultipleHiddenInput
368 def __init__(self
, choices
=(), required
=True, widget
=SelectMultiple
, label
=None, initial
=None, help_text
=None):
369 super(MultipleChoiceField
, self
).__init
__(choices
, required
, widget
, label
, initial
, help_text
)
371 def clean(self
, value
):
373 Validates that the input is a list or tuple.
375 if self
.required
and not value
:
376 raise ValidationError(gettext(u
'This field is required.'))
377 elif not self
.required
and not value
:
379 if not isinstance(value
, (list, tuple)):
380 raise ValidationError(gettext(u
'Enter a list of values.'))
383 val
= smart_unicode(val
)
384 new_value
.append(val
)
385 # Validate that each value in the value list is in self.choices.
386 valid_values
= set([smart_unicode(k
) for k
, v
in self
.choices
])
387 for val
in new_value
:
388 if val
not in valid_values
:
389 raise ValidationError(gettext(u
'Select a valid choice. %s is not one of the available choices.') % val
)
392 class ComboField(Field
):
394 A Field whose clean() method calls multiple Field clean() methods.
396 def __init__(self
, fields
=(), *args
, **kwargs
):
397 super(ComboField
, self
).__init
__(*args
, **kwargs
)
398 # Set 'required' to False on the individual fields, because the
399 # required validation will be handled by ComboField, not by those
405 def clean(self
, value
):
407 Validates the given value against all of self.fields, which is a
408 list of Field instances.
410 super(ComboField
, self
).clean(value
)
411 for field
in self
.fields
:
412 value
= field
.clean(value
)
415 class MultiValueField(Field
):
417 A Field that is composed of multiple Fields.
419 Its clean() method takes a "decompressed" list of values. Each value in
420 this list is cleaned by the corresponding field -- the first value is
421 cleaned by the first field, the second value is cleaned by the second
422 field, etc. Once all fields are cleaned, the list of clean values is
423 "compressed" into a single value.
425 Subclasses should implement compress(), which specifies how a list of
426 valid values should be converted to a single value. Subclasses should not
427 have to implement clean().
429 You'll probably want to use this with MultiWidget.
431 def __init__(self
, fields
=(), *args
, **kwargs
):
432 super(MultiValueField
, self
).__init
__(*args
, **kwargs
)
433 # Set 'required' to False on the individual fields, because the
434 # required validation will be handled by MultiValueField, not by those
440 def clean(self
, value
):
442 Validates every value in the given list. A value is validated against
443 the corresponding Field in self.fields.
445 For example, if this MultiValueField was instantiated with
446 fields=(DateField(), TimeField()), clean() would call
447 DateField.clean(value[0]) and TimeField.clean(value[1]).
451 if self
.required
and not value
:
452 raise ValidationError(gettext(u
'This field is required.'))
453 elif not self
.required
and not value
:
454 return self
.compress([])
455 if not isinstance(value
, (list, tuple)):
456 raise ValidationError(gettext(u
'Enter a list of values.'))
457 for i
, field
in enumerate(self
.fields
):
459 field_value
= value
[i
]
462 if self
.required
and field_value
in EMPTY_VALUES
:
463 raise ValidationError(gettext(u
'This field is required.'))
465 clean_data
.append(field
.clean(field_value
))
466 except ValidationError
, e
:
467 # Collect all validation errors in a single list, which we'll
468 # raise at the end of clean(), rather than raising a single
469 # exception for the first error we encounter.
470 errors
.extend(e
.messages
)
472 raise ValidationError(errors
)
473 return self
.compress(clean_data
)
475 def compress(self
, data_list
):
477 Returns a single value for the given list of values. The values can be
480 For example, if this MultiValueField was instantiated with
481 fields=(DateField(), TimeField()), this might return a datetime
482 object created by combining the date and time in data_list.
484 raise NotImplementedError('Subclasses must implement this method.')
486 class SplitDateTimeField(MultiValueField
):
487 def __init__(self
, *args
, **kwargs
):
488 fields
= (DateField(), TimeField())
489 super(SplitDateTimeField
, self
).__init
__(fields
, *args
, **kwargs
)
491 def compress(self
, data_list
):
493 return datetime
.datetime
.combine(*data_list
)