web/lib/django/forms/fields.py
changeset 29 cc9b7e14412b
parent 0 0d40e90630ef
equal deleted inserted replaced
28:b758351d191f 29:cc9b7e14412b
     1 """
     1 """
     2 Field classes.
     2 Field classes.
     3 """
     3 """
     4 
     4 
     5 import copy
       
     6 import datetime
     5 import datetime
     7 import os
     6 import os
     8 import re
     7 import re
     9 import time
     8 import time
    10 import urlparse
     9 import urlparse
       
    10 import warnings
       
    11 from decimal import Decimal, DecimalException
    11 try:
    12 try:
    12     from cStringIO import StringIO
    13     from cStringIO import StringIO
    13 except ImportError:
    14 except ImportError:
    14     from StringIO import StringIO
    15     from StringIO import StringIO
    15 
    16 
    16 # Python 2.3 fallbacks
    17 from django.core.exceptions import ValidationError
    17 try:
    18 from django.core import validators
    18     from decimal import Decimal, DecimalException
    19 import django.utils.copycompat as copy
    19 except ImportError:
    20 from django.utils import formats
    20     from django.utils._decimal import Decimal, DecimalException
       
    21 try:
       
    22     set
       
    23 except NameError:
       
    24     from sets import Set as set
       
    25 
       
    26 import django.core.exceptions
       
    27 from django.utils.translation import ugettext_lazy as _
    21 from django.utils.translation import ugettext_lazy as _
    28 from django.utils.encoding import smart_unicode, smart_str
    22 from django.utils.encoding import smart_unicode, smart_str
    29 
    23 from django.utils.functional import lazy
    30 from util import ErrorList, ValidationError
    24 
    31 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget
    25 # Provide this import for backwards compatibility.
       
    26 from django.core.validators import EMPTY_VALUES
       
    27 
       
    28 from util import ErrorList
       
    29 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, \
       
    30         FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, \
       
    31         DateInput, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget
    32 
    32 
    33 __all__ = (
    33 __all__ = (
    34     'Field', 'CharField', 'IntegerField',
    34     'Field', 'CharField', 'IntegerField',
    35     'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
    35     'DEFAULT_DATE_INPUT_FORMATS', 'DateField',
    36     'DEFAULT_TIME_INPUT_FORMATS', 'TimeField',
    36     'DEFAULT_TIME_INPUT_FORMATS', 'TimeField',
    40     'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
    40     'ComboField', 'MultiValueField', 'FloatField', 'DecimalField',
    41     'SplitDateTimeField', 'IPAddressField', 'FilePathField', 'SlugField',
    41     'SplitDateTimeField', 'IPAddressField', 'FilePathField', 'SlugField',
    42     'TypedChoiceField'
    42     'TypedChoiceField'
    43 )
    43 )
    44 
    44 
    45 # These values, if given to to_python(), will trigger the self.required check.
    45 def en_format(name):
    46 EMPTY_VALUES = (None, '')
    46     """
    47 
    47     Helper function to stay backward compatible.
       
    48     """
       
    49     from django.conf.locale.en import formats
       
    50     warnings.warn(
       
    51         "`django.forms.fields.DEFAULT_%s` is deprecated; use `django.utils.formats.get_format('%s')` instead." % (name, name),
       
    52         PendingDeprecationWarning
       
    53     )
       
    54     return getattr(formats, name)
       
    55 
       
    56 DEFAULT_DATE_INPUT_FORMATS = lazy(lambda: en_format('DATE_INPUT_FORMATS'), tuple, list)()
       
    57 DEFAULT_TIME_INPUT_FORMATS = lazy(lambda: en_format('TIME_INPUT_FORMATS'), tuple, list)()
       
    58 DEFAULT_DATETIME_INPUT_FORMATS = lazy(lambda: en_format('DATETIME_INPUT_FORMATS'), tuple, list)()
    48 
    59 
    49 class Field(object):
    60 class Field(object):
    50     widget = TextInput # Default widget to use when rendering this type of Field.
    61     widget = TextInput # Default widget to use when rendering this type of Field.
    51     hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden".
    62     hidden_widget = HiddenInput # Default widget to use when rendering this as "hidden".
       
    63     default_validators = [] # Default set of validators
    52     default_error_messages = {
    64     default_error_messages = {
    53         'required': _(u'This field is required.'),
    65         'required': _(u'This field is required.'),
    54         'invalid': _(u'Enter a valid value.'),
    66         'invalid': _(u'Enter a valid value.'),
    55     }
    67     }
    56 
    68 
    57     # Tracks each time a Field instance is created. Used to retain order.
    69     # Tracks each time a Field instance is created. Used to retain order.
    58     creation_counter = 0
    70     creation_counter = 0
    59 
    71 
    60     def __init__(self, required=True, widget=None, label=None, initial=None,
    72     def __init__(self, required=True, widget=None, label=None, initial=None,
    61                  help_text=None, error_messages=None, show_hidden_initial=False):
    73                  help_text=None, error_messages=None, show_hidden_initial=False,
       
    74                  validators=[], localize=False):
    62         # required -- Boolean that specifies whether the field is required.
    75         # required -- Boolean that specifies whether the field is required.
    63         #             True by default.
    76         #             True by default.
    64         # widget -- A Widget class, or instance of a Widget class, that should
    77         # widget -- A Widget class, or instance of a Widget class, that should
    65         #           be used for this Field when displaying it. Each Field has a
    78         #           be used for this Field when displaying it. Each Field has a
    66         #           default Widget that it'll use if you don't specify this. In
    79         #           default Widget that it'll use if you don't specify this. In
    70         #          version of the form field name, if the Field is part of a
    83         #          version of the form field name, if the Field is part of a
    71         #          Form.
    84         #          Form.
    72         # initial -- A value to use in this Field's initial display. This value
    85         # initial -- A value to use in this Field's initial display. This value
    73         #            is *not* used as a fallback if data isn't given.
    86         #            is *not* used as a fallback if data isn't given.
    74         # help_text -- An optional string to use as "help text" for this Field.
    87         # help_text -- An optional string to use as "help text" for this Field.
       
    88         # error_messages -- An optional dictionary to override the default
       
    89         #                   messages that the field will raise.
    75         # show_hidden_initial -- Boolean that specifies if it is needed to render a
    90         # show_hidden_initial -- Boolean that specifies if it is needed to render a
    76         #                        hidden widget with initial value after widget.
    91         #                        hidden widget with initial value after widget.
       
    92         # validators -- List of addtional validators to use
       
    93         # localize -- Boolean that specifies if the field should be localized.
    77         if label is not None:
    94         if label is not None:
    78             label = smart_unicode(label)
    95             label = smart_unicode(label)
    79         self.required, self.label, self.initial = required, label, initial
    96         self.required, self.label, self.initial = required, label, initial
    80         self.show_hidden_initial = show_hidden_initial
    97         self.show_hidden_initial = show_hidden_initial
    81         if help_text is None:
    98         if help_text is None:
    84             self.help_text = smart_unicode(help_text)
   101             self.help_text = smart_unicode(help_text)
    85         widget = widget or self.widget
   102         widget = widget or self.widget
    86         if isinstance(widget, type):
   103         if isinstance(widget, type):
    87             widget = widget()
   104             widget = widget()
    88 
   105 
       
   106         # Trigger the localization machinery if needed.
       
   107         self.localize = localize
       
   108 
    89         # Hook into self.widget_attrs() for any Field-specific HTML attributes.
   109         # Hook into self.widget_attrs() for any Field-specific HTML attributes.
    90         extra_attrs = self.widget_attrs(widget)
   110         extra_attrs = self.widget_attrs(widget)
    91         if extra_attrs:
   111         if extra_attrs:
    92             widget.attrs.update(extra_attrs)
   112             widget.attrs.update(extra_attrs)
    93 
   113 
    95 
   115 
    96         # Increase the creation counter, and save our local copy.
   116         # Increase the creation counter, and save our local copy.
    97         self.creation_counter = Field.creation_counter
   117         self.creation_counter = Field.creation_counter
    98         Field.creation_counter += 1
   118         Field.creation_counter += 1
    99 
   119 
   100         def set_class_error_messages(messages, klass):
       
   101             for base_class in klass.__bases__:
       
   102                 set_class_error_messages(messages, base_class)
       
   103             messages.update(getattr(klass, 'default_error_messages', {}))
       
   104 
       
   105         messages = {}
   120         messages = {}
   106         set_class_error_messages(messages, self.__class__)
   121         for c in reversed(self.__class__.__mro__):
       
   122             messages.update(getattr(c, 'default_error_messages', {}))
   107         messages.update(error_messages or {})
   123         messages.update(error_messages or {})
   108         self.error_messages = messages
   124         self.error_messages = messages
   109 
   125 
       
   126         self.validators = self.default_validators + validators
       
   127 
       
   128     def localize_value(self, value):
       
   129         return formats.localize_input(value)
       
   130 
       
   131     def to_python(self, value):
       
   132         return value
       
   133 
       
   134     def validate(self, value):
       
   135         if value in validators.EMPTY_VALUES and self.required:
       
   136             raise ValidationError(self.error_messages['required'])
       
   137 
       
   138     def run_validators(self, value):
       
   139         if value in validators.EMPTY_VALUES:
       
   140             return
       
   141         errors = []
       
   142         for v in self.validators:
       
   143             try:
       
   144                 v(value)
       
   145             except ValidationError, e:
       
   146                 if hasattr(e, 'code') and e.code in self.error_messages:
       
   147                     message = self.error_messages[e.code]
       
   148                     if e.params:
       
   149                         message = message % e.params
       
   150                     errors.append(message)
       
   151                 else:
       
   152                     errors.extend(e.messages)
       
   153         if errors:
       
   154             raise ValidationError(errors)
       
   155 
   110     def clean(self, value):
   156     def clean(self, value):
   111         """
   157         """
   112         Validates the given value and returns its "cleaned" value as an
   158         Validates the given value and returns its "cleaned" value as an
   113         appropriate Python object.
   159         appropriate Python object.
   114 
   160 
   115         Raises ValidationError for any errors.
   161         Raises ValidationError for any errors.
   116         """
   162         """
   117         if self.required and value in EMPTY_VALUES:
   163         value = self.to_python(value)
   118             raise ValidationError(self.error_messages['required'])
   164         self.validate(value)
       
   165         self.run_validators(value)
   119         return value
   166         return value
   120 
   167 
   121     def widget_attrs(self, widget):
   168     def widget_attrs(self, widget):
   122         """
   169         """
   123         Given a Widget instance (*not* a Widget class), returns a dictionary of
   170         Given a Widget instance (*not* a Widget class), returns a dictionary of
   131         memo[id(self)] = result
   178         memo[id(self)] = result
   132         result.widget = copy.deepcopy(self.widget, memo)
   179         result.widget = copy.deepcopy(self.widget, memo)
   133         return result
   180         return result
   134 
   181 
   135 class CharField(Field):
   182 class CharField(Field):
   136     default_error_messages = {
       
   137         'max_length': _(u'Ensure this value has at most %(max)d characters (it has %(length)d).'),
       
   138         'min_length': _(u'Ensure this value has at least %(min)d characters (it has %(length)d).'),
       
   139     }
       
   140 
       
   141     def __init__(self, max_length=None, min_length=None, *args, **kwargs):
   183     def __init__(self, max_length=None, min_length=None, *args, **kwargs):
   142         self.max_length, self.min_length = max_length, min_length
   184         self.max_length, self.min_length = max_length, min_length
   143         super(CharField, self).__init__(*args, **kwargs)
   185         super(CharField, self).__init__(*args, **kwargs)
   144 
   186         if min_length is not None:
   145     def clean(self, value):
   187             self.validators.append(validators.MinLengthValidator(min_length))
   146         "Validates max_length and min_length. Returns a Unicode object."
   188         if max_length is not None:
   147         super(CharField, self).clean(value)
   189             self.validators.append(validators.MaxLengthValidator(max_length))
   148         if value in EMPTY_VALUES:
   190 
       
   191     def to_python(self, value):
       
   192         "Returns a Unicode object."
       
   193         if value in validators.EMPTY_VALUES:
   149             return u''
   194             return u''
   150         value = smart_unicode(value)
   195         return smart_unicode(value)
   151         value_length = len(value)
       
   152         if self.max_length is not None and value_length > self.max_length:
       
   153             raise ValidationError(self.error_messages['max_length'] % {'max': self.max_length, 'length': value_length})
       
   154         if self.min_length is not None and value_length < self.min_length:
       
   155             raise ValidationError(self.error_messages['min_length'] % {'min': self.min_length, 'length': value_length})
       
   156         return value
       
   157 
   196 
   158     def widget_attrs(self, widget):
   197     def widget_attrs(self, widget):
   159         if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)):
   198         if self.max_length is not None and isinstance(widget, (TextInput, PasswordInput)):
   160             # The HTML attribute is maxlength, not max_length.
   199             # The HTML attribute is maxlength, not max_length.
   161             return {'maxlength': str(self.max_length)}
   200             return {'maxlength': str(self.max_length)}
   162 
   201 
   163 class IntegerField(Field):
   202 class IntegerField(Field):
   164     default_error_messages = {
   203     default_error_messages = {
   165         'invalid': _(u'Enter a whole number.'),
   204         'invalid': _(u'Enter a whole number.'),
   166         'max_value': _(u'Ensure this value is less than or equal to %s.'),
   205         'max_value': _(u'Ensure this value is less than or equal to %(limit_value)s.'),
   167         'min_value': _(u'Ensure this value is greater than or equal to %s.'),
   206         'min_value': _(u'Ensure this value is greater than or equal to %(limit_value)s.'),
   168     }
   207     }
   169 
   208 
   170     def __init__(self, max_value=None, min_value=None, *args, **kwargs):
   209     def __init__(self, max_value=None, min_value=None, *args, **kwargs):
   171         self.max_value, self.min_value = max_value, min_value
       
   172         super(IntegerField, self).__init__(*args, **kwargs)
   210         super(IntegerField, self).__init__(*args, **kwargs)
   173 
   211 
   174     def clean(self, value):
   212         if max_value is not None:
       
   213             self.validators.append(validators.MaxValueValidator(max_value))
       
   214         if min_value is not None:
       
   215             self.validators.append(validators.MinValueValidator(min_value))
       
   216 
       
   217     def to_python(self, value):
   175         """
   218         """
   176         Validates that int() can be called on the input. Returns the result
   219         Validates that int() can be called on the input. Returns the result
   177         of int(). Returns None for empty values.
   220         of int(). Returns None for empty values.
   178         """
   221         """
   179         super(IntegerField, self).clean(value)
   222         value = super(IntegerField, self).to_python(value)
   180         if value in EMPTY_VALUES:
   223         if value in validators.EMPTY_VALUES:
   181             return None
   224             return None
       
   225         if self.localize:
       
   226             value = formats.sanitize_separators(value)
   182         try:
   227         try:
   183             value = int(str(value))
   228             value = int(str(value))
   184         except (ValueError, TypeError):
   229         except (ValueError, TypeError):
   185             raise ValidationError(self.error_messages['invalid'])
   230             raise ValidationError(self.error_messages['invalid'])
   186         if self.max_value is not None and value > self.max_value:
       
   187             raise ValidationError(self.error_messages['max_value'] % self.max_value)
       
   188         if self.min_value is not None and value < self.min_value:
       
   189             raise ValidationError(self.error_messages['min_value'] % self.min_value)
       
   190         return value
   231         return value
   191 
   232 
   192 class FloatField(Field):
   233 class FloatField(IntegerField):
   193     default_error_messages = {
   234     default_error_messages = {
   194         'invalid': _(u'Enter a number.'),
   235         'invalid': _(u'Enter a number.'),
   195         'max_value': _(u'Ensure this value is less than or equal to %s.'),
   236     }
   196         'min_value': _(u'Ensure this value is greater than or equal to %s.'),
   237 
   197     }
   238     def to_python(self, value):
   198 
   239         """
   199     def __init__(self, max_value=None, min_value=None, *args, **kwargs):
   240         Validates that float() can be called on the input. Returns the result
   200         self.max_value, self.min_value = max_value, min_value
   241         of float(). Returns None for empty values.
   201         Field.__init__(self, *args, **kwargs)
   242         """
   202 
   243         value = super(IntegerField, self).to_python(value)
   203     def clean(self, value):
   244         if value in validators.EMPTY_VALUES:
   204         """
       
   205         Validates that float() can be called on the input. Returns a float.
       
   206         Returns None for empty values.
       
   207         """
       
   208         super(FloatField, self).clean(value)
       
   209         if not self.required and value in EMPTY_VALUES:
       
   210             return None
   245             return None
       
   246         if self.localize:
       
   247             value = formats.sanitize_separators(value)
   211         try:
   248         try:
   212             value = float(value)
   249             value = float(value)
   213         except (ValueError, TypeError):
   250         except (ValueError, TypeError):
   214             raise ValidationError(self.error_messages['invalid'])
   251             raise ValidationError(self.error_messages['invalid'])
   215         if self.max_value is not None and value > self.max_value:
       
   216             raise ValidationError(self.error_messages['max_value'] % self.max_value)
       
   217         if self.min_value is not None and value < self.min_value:
       
   218             raise ValidationError(self.error_messages['min_value'] % self.min_value)
       
   219         return value
   252         return value
   220 
   253 
   221 class DecimalField(Field):
   254 class DecimalField(Field):
   222     default_error_messages = {
   255     default_error_messages = {
   223         'invalid': _(u'Enter a number.'),
   256         'invalid': _(u'Enter a number.'),
   224         'max_value': _(u'Ensure this value is less than or equal to %s.'),
   257         'max_value': _(u'Ensure this value is less than or equal to %(limit_value)s.'),
   225         'min_value': _(u'Ensure this value is greater than or equal to %s.'),
   258         'min_value': _(u'Ensure this value is greater than or equal to %(limit_value)s.'),
   226         'max_digits': _('Ensure that there are no more than %s digits in total.'),
   259         'max_digits': _('Ensure that there are no more than %s digits in total.'),
   227         'max_decimal_places': _('Ensure that there are no more than %s decimal places.'),
   260         'max_decimal_places': _('Ensure that there are no more than %s decimal places.'),
   228         'max_whole_digits': _('Ensure that there are no more than %s digits before the decimal point.')
   261         'max_whole_digits': _('Ensure that there are no more than %s digits before the decimal point.')
   229     }
   262     }
   230 
   263 
   231     def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs):
   264     def __init__(self, max_value=None, min_value=None, max_digits=None, decimal_places=None, *args, **kwargs):
   232         self.max_value, self.min_value = max_value, min_value
       
   233         self.max_digits, self.decimal_places = max_digits, decimal_places
   265         self.max_digits, self.decimal_places = max_digits, decimal_places
   234         Field.__init__(self, *args, **kwargs)
   266         Field.__init__(self, *args, **kwargs)
   235 
   267 
   236     def clean(self, value):
   268         if max_value is not None:
       
   269             self.validators.append(validators.MaxValueValidator(max_value))
       
   270         if min_value is not None:
       
   271             self.validators.append(validators.MinValueValidator(min_value))
       
   272 
       
   273     def to_python(self, value):
   237         """
   274         """
   238         Validates that the input is a decimal number. Returns a Decimal
   275         Validates that the input is a decimal number. Returns a Decimal
   239         instance. Returns None for empty values. Ensures that there are no more
   276         instance. Returns None for empty values. Ensures that there are no more
   240         than max_digits in the number, and no more than decimal_places digits
   277         than max_digits in the number, and no more than decimal_places digits
   241         after the decimal point.
   278         after the decimal point.
   242         """
   279         """
   243         super(DecimalField, self).clean(value)
   280         if value in validators.EMPTY_VALUES:
   244         if not self.required and value in EMPTY_VALUES:
       
   245             return None
   281             return None
       
   282         if self.localize:
       
   283             value = formats.sanitize_separators(value)
   246         value = smart_str(value).strip()
   284         value = smart_str(value).strip()
   247         try:
   285         try:
   248             value = Decimal(value)
   286             value = Decimal(value)
   249         except DecimalException:
   287         except DecimalException:
   250             raise ValidationError(self.error_messages['invalid'])
   288             raise ValidationError(self.error_messages['invalid'])
   251 
   289         return value
       
   290 
       
   291     def validate(self, value):
       
   292         super(DecimalField, self).validate(value)
       
   293         if value in validators.EMPTY_VALUES:
       
   294             return
       
   295         # Check for NaN, Inf and -Inf values. We can't compare directly for NaN,
       
   296         # since it is never equal to itself. However, NaN is the only value that
       
   297         # isn't equal to itself, so we can use this to identify NaN
       
   298         if value != value or value == Decimal("Inf") or value == Decimal("-Inf"):
       
   299             raise ValidationError(self.error_messages['invalid'])
   252         sign, digittuple, exponent = value.as_tuple()
   300         sign, digittuple, exponent = value.as_tuple()
   253         decimals = abs(exponent)
   301         decimals = abs(exponent)
   254         # digittuple doesn't include any leading zeros.
   302         # digittuple doesn't include any leading zeros.
   255         digits = len(digittuple)
   303         digits = len(digittuple)
   256         if decimals > digits:
   304         if decimals > digits:
   259             # 0 before the decimal point as a digit since that would mean
   307             # 0 before the decimal point as a digit since that would mean
   260             # we would not allow max_digits = decimal_places.
   308             # we would not allow max_digits = decimal_places.
   261             digits = decimals
   309             digits = decimals
   262         whole_digits = digits - decimals
   310         whole_digits = digits - decimals
   263 
   311 
   264         if self.max_value is not None and value > self.max_value:
       
   265             raise ValidationError(self.error_messages['max_value'] % self.max_value)
       
   266         if self.min_value is not None and value < self.min_value:
       
   267             raise ValidationError(self.error_messages['min_value'] % self.min_value)
       
   268         if self.max_digits is not None and digits > self.max_digits:
   312         if self.max_digits is not None and digits > self.max_digits:
   269             raise ValidationError(self.error_messages['max_digits'] % self.max_digits)
   313             raise ValidationError(self.error_messages['max_digits'] % self.max_digits)
   270         if self.decimal_places is not None and decimals > self.decimal_places:
   314         if self.decimal_places is not None and decimals > self.decimal_places:
   271             raise ValidationError(self.error_messages['max_decimal_places'] % self.decimal_places)
   315             raise ValidationError(self.error_messages['max_decimal_places'] % self.decimal_places)
   272         if self.max_digits is not None and self.decimal_places is not None and whole_digits > (self.max_digits - self.decimal_places):
   316         if self.max_digits is not None and self.decimal_places is not None and whole_digits > (self.max_digits - self.decimal_places):
   273             raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places))
   317             raise ValidationError(self.error_messages['max_whole_digits'] % (self.max_digits - self.decimal_places))
   274         return value
   318         return value
   275 
   319 
   276 DEFAULT_DATE_INPUT_FORMATS = (
       
   277     '%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', # '2006-10-25', '10/25/2006', '10/25/06'
       
   278     '%b %d %Y', '%b %d, %Y',            # 'Oct 25 2006', 'Oct 25, 2006'
       
   279     '%d %b %Y', '%d %b, %Y',            # '25 Oct 2006', '25 Oct, 2006'
       
   280     '%B %d %Y', '%B %d, %Y',            # 'October 25 2006', 'October 25, 2006'
       
   281     '%d %B %Y', '%d %B, %Y',            # '25 October 2006', '25 October, 2006'
       
   282 )
       
   283 
       
   284 class DateField(Field):
   320 class DateField(Field):
   285     widget = DateInput
   321     widget = DateInput
   286     default_error_messages = {
   322     default_error_messages = {
   287         'invalid': _(u'Enter a valid date.'),
   323         'invalid': _(u'Enter a valid date.'),
   288     }
   324     }
   289 
   325 
   290     def __init__(self, input_formats=None, *args, **kwargs):
   326     def __init__(self, input_formats=None, *args, **kwargs):
   291         super(DateField, self).__init__(*args, **kwargs)
   327         super(DateField, self).__init__(*args, **kwargs)
   292         self.input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS
   328         self.input_formats = input_formats
   293 
   329 
   294     def clean(self, value):
   330     def to_python(self, value):
   295         """
   331         """
   296         Validates that the input can be converted to a date. Returns a Python
   332         Validates that the input can be converted to a date. Returns a Python
   297         datetime.date object.
   333         datetime.date object.
   298         """
   334         """
   299         super(DateField, self).clean(value)
   335         if value in validators.EMPTY_VALUES:
   300         if value in EMPTY_VALUES:
       
   301             return None
   336             return None
   302         if isinstance(value, datetime.datetime):
   337         if isinstance(value, datetime.datetime):
   303             return value.date()
   338             return value.date()
   304         if isinstance(value, datetime.date):
   339         if isinstance(value, datetime.date):
   305             return value
   340             return value
   306         for format in self.input_formats:
   341         for format in self.input_formats or formats.get_format('DATE_INPUT_FORMATS'):
   307             try:
   342             try:
   308                 return datetime.date(*time.strptime(value, format)[:3])
   343                 return datetime.date(*time.strptime(value, format)[:3])
   309             except ValueError:
   344             except ValueError:
   310                 continue
   345                 continue
   311         raise ValidationError(self.error_messages['invalid'])
   346         raise ValidationError(self.error_messages['invalid'])
   312 
   347 
   313 DEFAULT_TIME_INPUT_FORMATS = (
       
   314     '%H:%M:%S',     # '14:30:59'
       
   315     '%H:%M',        # '14:30'
       
   316 )
       
   317 
       
   318 class TimeField(Field):
   348 class TimeField(Field):
   319     widget = TimeInput
   349     widget = TimeInput
   320     default_error_messages = {
   350     default_error_messages = {
   321         'invalid': _(u'Enter a valid time.')
   351         'invalid': _(u'Enter a valid time.')
   322     }
   352     }
   323 
   353 
   324     def __init__(self, input_formats=None, *args, **kwargs):
   354     def __init__(self, input_formats=None, *args, **kwargs):
   325         super(TimeField, self).__init__(*args, **kwargs)
   355         super(TimeField, self).__init__(*args, **kwargs)
   326         self.input_formats = input_formats or DEFAULT_TIME_INPUT_FORMATS
   356         self.input_formats = input_formats
   327 
   357 
   328     def clean(self, value):
   358     def to_python(self, value):
   329         """
   359         """
   330         Validates that the input can be converted to a time. Returns a Python
   360         Validates that the input can be converted to a time. Returns a Python
   331         datetime.time object.
   361         datetime.time object.
   332         """
   362         """
   333         super(TimeField, self).clean(value)
   363         if value in validators.EMPTY_VALUES:
   334         if value in EMPTY_VALUES:
       
   335             return None
   364             return None
   336         if isinstance(value, datetime.time):
   365         if isinstance(value, datetime.time):
   337             return value
   366             return value
   338         for format in self.input_formats:
   367         for format in self.input_formats or formats.get_format('TIME_INPUT_FORMATS'):
   339             try:
   368             try:
   340                 return datetime.time(*time.strptime(value, format)[3:6])
   369                 return datetime.time(*time.strptime(value, format)[3:6])
   341             except ValueError:
   370             except ValueError:
   342                 continue
   371                 continue
   343         raise ValidationError(self.error_messages['invalid'])
   372         raise ValidationError(self.error_messages['invalid'])
   344 
   373 
   345 DEFAULT_DATETIME_INPUT_FORMATS = (
       
   346     '%Y-%m-%d %H:%M:%S',     # '2006-10-25 14:30:59'
       
   347     '%Y-%m-%d %H:%M',        # '2006-10-25 14:30'
       
   348     '%Y-%m-%d',              # '2006-10-25'
       
   349     '%m/%d/%Y %H:%M:%S',     # '10/25/2006 14:30:59'
       
   350     '%m/%d/%Y %H:%M',        # '10/25/2006 14:30'
       
   351     '%m/%d/%Y',              # '10/25/2006'
       
   352     '%m/%d/%y %H:%M:%S',     # '10/25/06 14:30:59'
       
   353     '%m/%d/%y %H:%M',        # '10/25/06 14:30'
       
   354     '%m/%d/%y',              # '10/25/06'
       
   355 )
       
   356 
       
   357 class DateTimeField(Field):
   374 class DateTimeField(Field):
   358     widget = DateTimeInput
   375     widget = DateTimeInput
   359     default_error_messages = {
   376     default_error_messages = {
   360         'invalid': _(u'Enter a valid date/time.'),
   377         'invalid': _(u'Enter a valid date/time.'),
   361     }
   378     }
   362 
   379 
   363     def __init__(self, input_formats=None, *args, **kwargs):
   380     def __init__(self, input_formats=None, *args, **kwargs):
   364         super(DateTimeField, self).__init__(*args, **kwargs)
   381         super(DateTimeField, self).__init__(*args, **kwargs)
   365         self.input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS
   382         self.input_formats = input_formats
   366 
   383 
   367     def clean(self, value):
   384     def to_python(self, value):
   368         """
   385         """
   369         Validates that the input can be converted to a datetime. Returns a
   386         Validates that the input can be converted to a datetime. Returns a
   370         Python datetime.datetime object.
   387         Python datetime.datetime object.
   371         """
   388         """
   372         super(DateTimeField, self).clean(value)
   389         if value in validators.EMPTY_VALUES:
   373         if value in EMPTY_VALUES:
       
   374             return None
   390             return None
   375         if isinstance(value, datetime.datetime):
   391         if isinstance(value, datetime.datetime):
   376             return value
   392             return value
   377         if isinstance(value, datetime.date):
   393         if isinstance(value, datetime.date):
   378             return datetime.datetime(value.year, value.month, value.day)
   394             return datetime.datetime(value.year, value.month, value.day)
   380             # Input comes from a SplitDateTimeWidget, for example. So, it's two
   396             # Input comes from a SplitDateTimeWidget, for example. So, it's two
   381             # components: date and time.
   397             # components: date and time.
   382             if len(value) != 2:
   398             if len(value) != 2:
   383                 raise ValidationError(self.error_messages['invalid'])
   399                 raise ValidationError(self.error_messages['invalid'])
   384             value = '%s %s' % tuple(value)
   400             value = '%s %s' % tuple(value)
   385         for format in self.input_formats:
   401         for format in self.input_formats or formats.get_format('DATETIME_INPUT_FORMATS'):
   386             try:
   402             try:
   387                 return datetime.datetime(*time.strptime(value, format)[:6])
   403                 return datetime.datetime(*time.strptime(value, format)[:6])
   388             except ValueError:
   404             except ValueError:
   389                 continue
   405                 continue
   390         raise ValidationError(self.error_messages['invalid'])
   406         raise ValidationError(self.error_messages['invalid'])
   403             kwargs['error_messages'] = error_messages
   419             kwargs['error_messages'] = error_messages
   404         super(RegexField, self).__init__(max_length, min_length, *args, **kwargs)
   420         super(RegexField, self).__init__(max_length, min_length, *args, **kwargs)
   405         if isinstance(regex, basestring):
   421         if isinstance(regex, basestring):
   406             regex = re.compile(regex)
   422             regex = re.compile(regex)
   407         self.regex = regex
   423         self.regex = regex
   408 
   424         self.validators.append(validators.RegexValidator(regex=regex))
   409     def clean(self, value):
   425 
   410         """
   426 class EmailField(CharField):
   411         Validates that the input matches the regular expression. Returns a
       
   412         Unicode object.
       
   413         """
       
   414         value = super(RegexField, self).clean(value)
       
   415         if value == u'':
       
   416             return value
       
   417         if not self.regex.search(value):
       
   418             raise ValidationError(self.error_messages['invalid'])
       
   419         return value
       
   420 
       
   421 email_re = re.compile(
       
   422     r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
       
   423     r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
       
   424     r')@(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?$', re.IGNORECASE)  # domain
       
   425 
       
   426 class EmailField(RegexField):
       
   427     default_error_messages = {
   427     default_error_messages = {
   428         'invalid': _(u'Enter a valid e-mail address.'),
   428         'invalid': _(u'Enter a valid e-mail address.'),
   429     }
   429     }
   430 
   430     default_validators = [validators.validate_email]
   431     def __init__(self, max_length=None, min_length=None, *args, **kwargs):
       
   432         RegexField.__init__(self, email_re, max_length, min_length, *args,
       
   433                             **kwargs)
       
   434 
       
   435 try:
       
   436     from django.conf import settings
       
   437     URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT
       
   438 except ImportError:
       
   439     # It's OK if Django settings aren't configured.
       
   440     URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)'
       
   441 
       
   442 
   431 
   443 class FileField(Field):
   432 class FileField(Field):
   444     widget = FileInput
   433     widget = FileInput
   445     default_error_messages = {
   434     default_error_messages = {
   446         'invalid': _(u"No file was submitted. Check the encoding type on the form."),
   435         'invalid': _(u"No file was submitted. Check the encoding type on the form."),
   451 
   440 
   452     def __init__(self, *args, **kwargs):
   441     def __init__(self, *args, **kwargs):
   453         self.max_length = kwargs.pop('max_length', None)
   442         self.max_length = kwargs.pop('max_length', None)
   454         super(FileField, self).__init__(*args, **kwargs)
   443         super(FileField, self).__init__(*args, **kwargs)
   455 
   444 
   456     def clean(self, data, initial=None):
   445     def to_python(self, data):
   457         super(FileField, self).clean(initial or data)
   446         if data in validators.EMPTY_VALUES:
   458         if not self.required and data in EMPTY_VALUES:
       
   459             return None
   447             return None
   460         elif not data and initial:
       
   461             return initial
       
   462 
   448 
   463         # UploadedFile objects should have name and size attributes.
   449         # UploadedFile objects should have name and size attributes.
   464         try:
   450         try:
   465             file_name = data.name
   451             file_name = data.name
   466             file_size = data.size
   452             file_size = data.size
   475         if not file_size:
   461         if not file_size:
   476             raise ValidationError(self.error_messages['empty'])
   462             raise ValidationError(self.error_messages['empty'])
   477 
   463 
   478         return data
   464         return data
   479 
   465 
       
   466     def clean(self, data, initial=None):
       
   467         if not data and initial:
       
   468             return initial
       
   469         return super(FileField, self).clean(data)
       
   470 
   480 class ImageField(FileField):
   471 class ImageField(FileField):
   481     default_error_messages = {
   472     default_error_messages = {
   482         'invalid_image': _(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."),
   473         'invalid_image': _(u"Upload a valid image. The file you uploaded was either not an image or a corrupted image."),
   483     }
   474     }
   484 
   475 
   485     def clean(self, data, initial=None):
   476     def to_python(self, data):
   486         """
   477         """
   487         Checks that the file-upload field data contains a valid image (GIF, JPG,
   478         Checks that the file-upload field data contains a valid image (GIF, JPG,
   488         PNG, possibly others -- whatever the Python Imaging Library supports).
   479         PNG, possibly others -- whatever the Python Imaging Library supports).
   489         """
   480         """
   490         f = super(ImageField, self).clean(data, initial)
   481         f = super(ImageField, self).to_python(data)
   491         if f is None:
   482         if f is None:
   492             return None
   483             return None
   493         elif not data and initial:
   484 
   494             return initial
   485         # Try to import PIL in either of the two ways it can end up installed.
   495         from PIL import Image
   486         try:
       
   487             from PIL import Image
       
   488         except ImportError:
       
   489             import Image
   496 
   490 
   497         # We need to get a file object for PIL. We might have a path or we might
   491         # We need to get a file object for PIL. We might have a path or we might
   498         # have to read the data into memory.
   492         # have to read the data into memory.
   499         if hasattr(data, 'temporary_file_path'):
   493         if hasattr(data, 'temporary_file_path'):
   500             file = data.temporary_file_path()
   494             file = data.temporary_file_path()
   528             raise ValidationError(self.error_messages['invalid_image'])
   522             raise ValidationError(self.error_messages['invalid_image'])
   529         if hasattr(f, 'seek') and callable(f.seek):
   523         if hasattr(f, 'seek') and callable(f.seek):
   530             f.seek(0)
   524             f.seek(0)
   531         return f
   525         return f
   532 
   526 
   533 url_re = re.compile(
   527 class URLField(CharField):
   534     r'^https?://' # http:// or https://
       
   535     r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+[A-Z]{2,6}\.?|' #domain...
       
   536     r'localhost|' #localhost...
       
   537     r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
       
   538     r'(?::\d+)?' # optional port
       
   539     r'(?:/?|/\S+)$', re.IGNORECASE)
       
   540 
       
   541 class URLField(RegexField):
       
   542     default_error_messages = {
   528     default_error_messages = {
   543         'invalid': _(u'Enter a valid URL.'),
   529         'invalid': _(u'Enter a valid URL.'),
   544         'invalid_link': _(u'This URL appears to be a broken link.'),
   530         'invalid_link': _(u'This URL appears to be a broken link.'),
   545     }
   531     }
   546 
   532 
   547     def __init__(self, max_length=None, min_length=None, verify_exists=False,
   533     def __init__(self, max_length=None, min_length=None, verify_exists=False,
   548             validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs):
   534             validator_user_agent=validators.URL_VALIDATOR_USER_AGENT, *args, **kwargs):
   549         super(URLField, self).__init__(url_re, max_length, min_length, *args,
   535         super(URLField, self).__init__(max_length, min_length, *args,
   550                                        **kwargs)
   536                                        **kwargs)
   551         self.verify_exists = verify_exists
   537         self.validators.append(validators.URLValidator(verify_exists=verify_exists, validator_user_agent=validator_user_agent))
   552         self.user_agent = validator_user_agent
   538 
   553 
   539     def to_python(self, value):
   554     def clean(self, value):
   540         if value:
   555         # If no URL scheme given, assume http://
   541             if '://' not in value:
   556         if value and '://' not in value:
   542                 # If no URL scheme given, assume http://
   557             value = u'http://%s' % value
   543                 value = u'http://%s' % value
   558         # If no URL path given, assume /
   544             url_fields = list(urlparse.urlsplit(value))
   559         if value and not urlparse.urlsplit(value)[2]:
   545             if not url_fields[2]:
   560             value += '/'
   546                 # the path portion may need to be added before query params
   561         value = super(URLField, self).clean(value)
   547                 url_fields[2] = '/'
   562         if value == u'':
   548                 value = urlparse.urlunsplit(url_fields)
   563             return value
   549         return super(URLField, self).to_python(value)
   564         if self.verify_exists:
       
   565             import urllib2
       
   566             headers = {
       
   567                 "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5",
       
   568                 "Accept-Language": "en-us,en;q=0.5",
       
   569                 "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7",
       
   570                 "Connection": "close",
       
   571                 "User-Agent": self.user_agent,
       
   572             }
       
   573             try:
       
   574                 req = urllib2.Request(value, None, headers)
       
   575                 u = urllib2.urlopen(req)
       
   576             except ValueError:
       
   577                 raise ValidationError(self.error_messages['invalid'])
       
   578             except: # urllib2.URLError, httplib.InvalidURL, etc.
       
   579                 raise ValidationError(self.error_messages['invalid_link'])
       
   580         return value
       
   581 
   550 
   582 class BooleanField(Field):
   551 class BooleanField(Field):
   583     widget = CheckboxInput
   552     widget = CheckboxInput
   584 
   553 
   585     def clean(self, value):
   554     def to_python(self, value):
   586         """Returns a Python boolean object."""
   555         """Returns a Python boolean object."""
   587         # Explicitly check for the string 'False', which is what a hidden field
   556         # Explicitly check for the string 'False', which is what a hidden field
   588         # will submit for False. Also check for '0', since this is what
   557         # will submit for False. Also check for '0', since this is what
   589         # RadioSelect will provide. Because bool("True") == bool('1') == True,
   558         # RadioSelect will provide. Because bool("True") == bool('1') == True,
   590         # we don't need to handle that explicitly.
   559         # we don't need to handle that explicitly.
   591         if value in ('False', '0'):
   560         if value in ('False', '0'):
   592             value = False
   561             value = False
   593         else:
   562         else:
   594             value = bool(value)
   563             value = bool(value)
   595         super(BooleanField, self).clean(value)
   564         value = super(BooleanField, self).to_python(value)
   596         if not value and self.required:
   565         if not value and self.required:
   597             raise ValidationError(self.error_messages['required'])
   566             raise ValidationError(self.error_messages['required'])
   598         return value
   567         return value
   599 
   568 
   600 class NullBooleanField(BooleanField):
   569 class NullBooleanField(BooleanField):
   602     A field whose valid values are None, True and False. Invalid values are
   571     A field whose valid values are None, True and False. Invalid values are
   603     cleaned to None.
   572     cleaned to None.
   604     """
   573     """
   605     widget = NullBooleanSelect
   574     widget = NullBooleanSelect
   606 
   575 
   607     def clean(self, value):
   576     def to_python(self, value):
   608         """
   577         """
   609         Explicitly checks for the string 'True' and 'False', which is what a
   578         Explicitly checks for the string 'True' and 'False', which is what a
   610         hidden field will submit for True and False, and for '1' and '0', which
   579         hidden field will submit for True and False, and for '1' and '0', which
   611         is what a RadioField will submit. Unlike the Booleanfield we need to
   580         is what a RadioField will submit. Unlike the Booleanfield we need to
   612         explicitly check for True, because we are not using the bool() function
   581         explicitly check for True, because we are not using the bool() function
   616         elif value in (False, 'False', '0'):
   585         elif value in (False, 'False', '0'):
   617             return False
   586             return False
   618         else:
   587         else:
   619             return None
   588             return None
   620 
   589 
       
   590     def validate(self, value):
       
   591         pass
       
   592 
   621 class ChoiceField(Field):
   593 class ChoiceField(Field):
   622     widget = Select
   594     widget = Select
   623     default_error_messages = {
   595     default_error_messages = {
   624         'invalid_choice': _(u'Select a valid choice. %(value)s is not one of the available choices.'),
   596         'invalid_choice': _(u'Select a valid choice. %(value)s is not one of the available choices.'),
   625     }
   597     }
   626 
   598 
   627     def __init__(self, choices=(), required=True, widget=None, label=None,
   599     def __init__(self, choices=(), required=True, widget=None, label=None,
   628                  initial=None, help_text=None, *args, **kwargs):
   600                  initial=None, help_text=None, *args, **kwargs):
   629         super(ChoiceField, self).__init__(required, widget, label, initial,
   601         super(ChoiceField, self).__init__(required=required, widget=widget, label=label,
   630                                           help_text, *args, **kwargs)
   602                                         initial=initial, help_text=help_text, *args, **kwargs)
   631         self.choices = choices
   603         self.choices = choices
   632 
   604 
   633     def _get_choices(self):
   605     def _get_choices(self):
   634         return self._choices
   606         return self._choices
   635 
   607 
   639         # it will be consumed more than once.
   611         # it will be consumed more than once.
   640         self._choices = self.widget.choices = list(value)
   612         self._choices = self.widget.choices = list(value)
   641 
   613 
   642     choices = property(_get_choices, _set_choices)
   614     choices = property(_get_choices, _set_choices)
   643 
   615 
   644     def clean(self, value):
   616     def to_python(self, value):
       
   617         "Returns a Unicode object."
       
   618         if value in validators.EMPTY_VALUES:
       
   619             return u''
       
   620         return smart_unicode(value)
       
   621 
       
   622     def validate(self, value):
   645         """
   623         """
   646         Validates that the input is in self.choices.
   624         Validates that the input is in self.choices.
   647         """
   625         """
   648         value = super(ChoiceField, self).clean(value)
   626         super(ChoiceField, self).validate(value)
   649         if value in EMPTY_VALUES:
   627         if value and not self.valid_value(value):
   650             value = u''
       
   651         value = smart_unicode(value)
       
   652         if value == u'':
       
   653             return value
       
   654         if not self.valid_value(value):
       
   655             raise ValidationError(self.error_messages['invalid_choice'] % {'value': value})
   628             raise ValidationError(self.error_messages['invalid_choice'] % {'value': value})
   656         return value
       
   657 
   629 
   658     def valid_value(self, value):
   630     def valid_value(self, value):
   659         "Check to see if the provided value is a valid choice"
   631         "Check to see if the provided value is a valid choice"
   660         for k, v in self.choices:
   632         for k, v in self.choices:
   661             if type(v) in (tuple, list):
   633             if isinstance(v, (list, tuple)):
   662                 # This is an optgroup, so look inside the group for options
   634                 # This is an optgroup, so look inside the group for options
   663                 for k2, v2 in v:
   635                 for k2, v2 in v:
   664                     if value == smart_unicode(k2):
   636                     if value == smart_unicode(k2):
   665                         return True
   637                         return True
   666             else:
   638             else:
   672     def __init__(self, *args, **kwargs):
   644     def __init__(self, *args, **kwargs):
   673         self.coerce = kwargs.pop('coerce', lambda val: val)
   645         self.coerce = kwargs.pop('coerce', lambda val: val)
   674         self.empty_value = kwargs.pop('empty_value', '')
   646         self.empty_value = kwargs.pop('empty_value', '')
   675         super(TypedChoiceField, self).__init__(*args, **kwargs)
   647         super(TypedChoiceField, self).__init__(*args, **kwargs)
   676 
   648 
   677     def clean(self, value):
   649     def to_python(self, value):
   678         """
   650         """
   679         Validate that the value is in self.choices and can be coerced to the
   651         Validate that the value is in self.choices and can be coerced to the
   680         right type.
   652         right type.
   681         """
   653         """
   682         value = super(TypedChoiceField, self).clean(value)
   654         value = super(TypedChoiceField, self).to_python(value)
   683         if value == self.empty_value or value in EMPTY_VALUES:
   655         super(TypedChoiceField, self).validate(value)
       
   656         if value == self.empty_value or value in validators.EMPTY_VALUES:
   684             return self.empty_value
   657             return self.empty_value
   685 
       
   686         # Hack alert: This field is purpose-made to use with Field.to_python as
       
   687         # a coercion function so that ModelForms with choices work. However,
       
   688         # Django's Field.to_python raises
       
   689         # django.core.exceptions.ValidationError, which is a *different*
       
   690         # exception than django.forms.util.ValidationError. So we need to catch
       
   691         # both.
       
   692         try:
   658         try:
   693             value = self.coerce(value)
   659             value = self.coerce(value)
   694         except (ValueError, TypeError, django.core.exceptions.ValidationError):
   660         except (ValueError, TypeError, ValidationError):
   695             raise ValidationError(self.error_messages['invalid_choice'] % {'value': value})
   661             raise ValidationError(self.error_messages['invalid_choice'] % {'value': value})
   696         return value
   662         return value
       
   663 
       
   664     def validate(self, value):
       
   665         pass
   697 
   666 
   698 class MultipleChoiceField(ChoiceField):
   667 class MultipleChoiceField(ChoiceField):
   699     hidden_widget = MultipleHiddenInput
   668     hidden_widget = MultipleHiddenInput
   700     widget = SelectMultiple
   669     widget = SelectMultiple
   701     default_error_messages = {
   670     default_error_messages = {
   702         'invalid_choice': _(u'Select a valid choice. %(value)s is not one of the available choices.'),
   671         'invalid_choice': _(u'Select a valid choice. %(value)s is not one of the available choices.'),
   703         'invalid_list': _(u'Enter a list of values.'),
   672         'invalid_list': _(u'Enter a list of values.'),
   704     }
   673     }
   705 
   674 
   706     def clean(self, value):
   675     def to_python(self, value):
       
   676         if not value:
       
   677             return []
       
   678         elif not isinstance(value, (list, tuple)):
       
   679             raise ValidationError(self.error_messages['invalid_list'])
       
   680         return [smart_unicode(val) for val in value]
       
   681 
       
   682     def validate(self, value):
   707         """
   683         """
   708         Validates that the input is a list or tuple.
   684         Validates that the input is a list or tuple.
   709         """
   685         """
   710         if self.required and not value:
   686         if self.required and not value:
   711             raise ValidationError(self.error_messages['required'])
   687             raise ValidationError(self.error_messages['required'])
   712         elif not self.required and not value:
       
   713             return []
       
   714         if not isinstance(value, (list, tuple)):
       
   715             raise ValidationError(self.error_messages['invalid_list'])
       
   716         new_value = [smart_unicode(val) for val in value]
       
   717         # Validate that each value in the value list is in self.choices.
   688         # Validate that each value in the value list is in self.choices.
   718         for val in new_value:
   689         for val in value:
   719             if not self.valid_value(val):
   690             if not self.valid_value(val):
   720                 raise ValidationError(self.error_messages['invalid_choice'] % {'value': val})
   691                 raise ValidationError(self.error_messages['invalid_choice'] % {'value': val})
   721         return new_value
       
   722 
   692 
   723 class ComboField(Field):
   693 class ComboField(Field):
   724     """
   694     """
   725     A Field whose clean() method calls multiple Field clean() methods.
   695     A Field whose clean() method calls multiple Field clean() methods.
   726     """
   696     """
   771         # individual fields.
   741         # individual fields.
   772         for f in fields:
   742         for f in fields:
   773             f.required = False
   743             f.required = False
   774         self.fields = fields
   744         self.fields = fields
   775 
   745 
       
   746     def validate(self, value):
       
   747         pass
       
   748 
   776     def clean(self, value):
   749     def clean(self, value):
   777         """
   750         """
   778         Validates every value in the given list. A value is validated against
   751         Validates every value in the given list. A value is validated against
   779         the corresponding Field in self.fields.
   752         the corresponding Field in self.fields.
   780 
   753 
   783         DateField.clean(value[0]) and TimeField.clean(value[1]).
   756         DateField.clean(value[0]) and TimeField.clean(value[1]).
   784         """
   757         """
   785         clean_data = []
   758         clean_data = []
   786         errors = ErrorList()
   759         errors = ErrorList()
   787         if not value or isinstance(value, (list, tuple)):
   760         if not value or isinstance(value, (list, tuple)):
   788             if not value or not [v for v in value if v not in EMPTY_VALUES]:
   761             if not value or not [v for v in value if v not in validators.EMPTY_VALUES]:
   789                 if self.required:
   762                 if self.required:
   790                     raise ValidationError(self.error_messages['required'])
   763                     raise ValidationError(self.error_messages['required'])
   791                 else:
   764                 else:
   792                     return self.compress([])
   765                     return self.compress([])
   793         else:
   766         else:
   795         for i, field in enumerate(self.fields):
   768         for i, field in enumerate(self.fields):
   796             try:
   769             try:
   797                 field_value = value[i]
   770                 field_value = value[i]
   798             except IndexError:
   771             except IndexError:
   799                 field_value = None
   772                 field_value = None
   800             if self.required and field_value in EMPTY_VALUES:
   773             if self.required and field_value in validators.EMPTY_VALUES:
   801                 raise ValidationError(self.error_messages['required'])
   774                 raise ValidationError(self.error_messages['required'])
   802             try:
   775             try:
   803                 clean_data.append(field.clean(field_value))
   776                 clean_data.append(field.clean(field_value))
   804             except ValidationError, e:
   777             except ValidationError, e:
   805                 # Collect all validation errors in a single list, which we'll
   778                 # Collect all validation errors in a single list, which we'll
   806                 # raise at the end of clean(), rather than raising a single
   779                 # raise at the end of clean(), rather than raising a single
   807                 # exception for the first error we encounter.
   780                 # exception for the first error we encounter.
   808                 errors.extend(e.messages)
   781                 errors.extend(e.messages)
   809         if errors:
   782         if errors:
   810             raise ValidationError(errors)
   783             raise ValidationError(errors)
   811         return self.compress(clean_data)
   784 
       
   785         out = self.compress(clean_data)
       
   786         self.validate(out)
       
   787         return out
   812 
   788 
   813     def compress(self, data_list):
   789     def compress(self, data_list):
   814         """
   790         """
   815         Returns a single value for the given list of values. The values can be
   791         Returns a single value for the given list of values. The values can be
   816         assumed to be valid.
   792         assumed to be valid.
   875 
   851 
   876     def compress(self, data_list):
   852     def compress(self, data_list):
   877         if data_list:
   853         if data_list:
   878             # Raise a validation error if time or date is empty
   854             # Raise a validation error if time or date is empty
   879             # (possible if SplitDateTimeField has required=False).
   855             # (possible if SplitDateTimeField has required=False).
   880             if data_list[0] in EMPTY_VALUES:
   856             if data_list[0] in validators.EMPTY_VALUES:
   881                 raise ValidationError(self.error_messages['invalid_date'])
   857                 raise ValidationError(self.error_messages['invalid_date'])
   882             if data_list[1] in EMPTY_VALUES:
   858             if data_list[1] in validators.EMPTY_VALUES:
   883                 raise ValidationError(self.error_messages['invalid_time'])
   859                 raise ValidationError(self.error_messages['invalid_time'])
   884             return datetime.datetime.combine(*data_list)
   860             return datetime.datetime.combine(*data_list)
   885         return None
   861         return None
   886 
   862 
   887 ipv4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$')
   863 
   888 
   864 class IPAddressField(CharField):
   889 class IPAddressField(RegexField):
       
   890     default_error_messages = {
   865     default_error_messages = {
   891         'invalid': _(u'Enter a valid IPv4 address.'),
   866         'invalid': _(u'Enter a valid IPv4 address.'),
   892     }
   867     }
   893 
   868     default_validators = [validators.validate_ipv4_address]
   894     def __init__(self, *args, **kwargs):
   869 
   895         super(IPAddressField, self).__init__(ipv4_re, *args, **kwargs)
   870 
   896 
   871 class SlugField(CharField):
   897 slug_re = re.compile(r'^[-\w]+$')
       
   898 
       
   899 class SlugField(RegexField):
       
   900     default_error_messages = {
   872     default_error_messages = {
   901         'invalid': _(u"Enter a valid 'slug' consisting of letters, numbers,"
   873         'invalid': _(u"Enter a valid 'slug' consisting of letters, numbers,"
   902                      u" underscores or hyphens."),
   874                      u" underscores or hyphens."),
   903     }
   875     }
   904 
   876     default_validators = [validators.validate_slug]
   905     def __init__(self, *args, **kwargs):
       
   906         super(SlugField, self).__init__(slug_re, *args, **kwargs)