Author: mtredinnick
Date: 2007-11-18 06:07:25 -0600 (Sun, 18 Nov 2007)
New Revision: 6693

Modified:
   django/branches/queryset-refactor/django/newforms/fields.py
   django/branches/queryset-refactor/django/newforms/util.py
   django/branches/queryset-refactor/django/templatetags/cache.py
   django/branches/queryset-refactor/django/test/testcases.py
   django/branches/queryset-refactor/docs/newforms.txt
Log:
queryset-refactor: Fixed up a few problems from the previous merge from trunk.


Modified: django/branches/queryset-refactor/django/newforms/fields.py
===================================================================
--- django/branches/queryset-refactor/django/newforms/fields.py 2007-11-18 
07:19:11 UTC (rev 6692)
+++ django/branches/queryset-refactor/django/newforms/fields.py 2007-11-18 
12:07:25 UTC (rev 6693)
@@ -49,7 +49,8 @@
     # Tracks each time a Field instance is created. Used to retain order.
     creation_counter = 0
 
-    def __init__(self, required=True, widget=None, label=None, initial=None, 
help_text=None):
+    def __init__(self, required=True, widget=None, label=None, initial=None,
+                 help_text=None, error_messages=None):
         # required -- Boolean that specifies whether the field is required.
         #             True by default.
         # widget -- A Widget class, or instance of a Widget class, that should
@@ -106,7 +107,7 @@
         Raises ValidationError for any errors.
         """
         if self.required and value in EMPTY_VALUES:
-            raise ValidationError(ugettext(u'This field is required.'))
+            raise ValidationError(self.error_messages['required'])
         return value
 
     def widget_attrs(self, widget):
@@ -141,9 +142,9 @@
         value = smart_unicode(value)
         value_length = len(value)
         if self.max_length is not None and value_length > self.max_length:
-            raise ValidationError(ugettext(u'Ensure this value has at most 
%(max)d characters (it has %(length)d).') % {'max': self.max_length, 'length': 
value_length})
+            raise ValidationError(self.error_messages['max_length'] % {'max': 
self.max_length, 'length': value_length})
         if self.min_length is not None and value_length < self.min_length:
-            raise ValidationError(ugettext(u'Ensure this value has at least 
%(min)d characters (it has %(length)d).') % {'min': self.min_length, 'length': 
value_length})
+            raise ValidationError(self.error_messages['min_length'] % {'min': 
self.min_length, 'length': value_length})
         return value
 
     def widget_attrs(self, widget):
@@ -173,11 +174,11 @@
         try:
             value = int(str(value))
         except (ValueError, TypeError):
-            raise ValidationError(ugettext(u'Enter a whole number.'))
+            raise ValidationError(self.error_messages['invalid'])
         if self.max_value is not None and value > self.max_value:
-            raise ValidationError(ugettext(u'Ensure this value is less than or 
equal to %s.') % self.max_value)
+            raise ValidationError(self.error_messages['max_value'] % 
self.max_value)
         if self.min_value is not None and value < self.min_value:
-            raise ValidationError(ugettext(u'Ensure this value is greater than 
or equal to %s.') % self.min_value)
+            raise ValidationError(self.error_messages['min_value'] % 
self.min_value)
         return value
 
 class FloatField(Field):
@@ -202,11 +203,11 @@
         try:
             value = float(value)
         except (ValueError, TypeError):
-            raise ValidationError(ugettext('Enter a number.'))
+            raise ValidationError(self.error_messages['invalid'])
         if self.max_value is not None and value > self.max_value:
-            raise ValidationError(ugettext('Ensure this value is less than or 
equal to %s.') % self.max_value)
+            raise ValidationError(self.error_messages['max_value'] % 
self.max_value)
         if self.min_value is not None and value < self.min_value:
-            raise ValidationError(ugettext('Ensure this value is greater than 
or equal to %s.') % self.min_value)
+            raise ValidationError(self.error_messages['min_value'] % 
self.min_value)
         return value
 
 class DecimalField(Field):
@@ -238,20 +239,20 @@
         try:
             value = Decimal(value)
         except DecimalException:
-            raise ValidationError(ugettext('Enter a number.'))
+            raise ValidationError(self.error_messages['invalid'])
         pieces = str(value).lstrip("-").split('.')
         decimals = (len(pieces) == 2) and len(pieces[1]) or 0
         digits = len(pieces[0])
         if self.max_value is not None and value > self.max_value:
-            raise ValidationError(ugettext('Ensure this value is less than or 
equal to %s.') % self.max_value)
+            raise ValidationError(self.error_messages['max_value'] % 
self.max_value)
         if self.min_value is not None and value < self.min_value:
-            raise ValidationError(ugettext('Ensure this value is greater than 
or equal to %s.') % self.min_value)
+            raise ValidationError(self.error_messages['min_value'] % 
self.min_value)
         if self.max_digits is not None and (digits + decimals) > 
self.max_digits:
-            raise ValidationError(ugettext('Ensure that there are no more than 
%s digits in total.') % self.max_digits)
+            raise ValidationError(self.error_messages['max_digits'] % 
self.max_digits)
         if self.decimal_places is not None and decimals > self.decimal_places:
-            raise ValidationError(ugettext('Ensure that there are no more than 
%s decimal places.') % self.decimal_places)
+            raise ValidationError(self.error_messages['max_decimal_places'] % 
self.decimal_places)
         if self.max_digits is not None and self.decimal_places is not None and 
digits > (self.max_digits - self.decimal_places):
-            raise ValidationError(ugettext('Ensure that there are no more than 
%s digits before the decimal point.') % (self.max_digits - self.decimal_places))
+            raise ValidationError(self.error_messages['max_whole_digits'] % 
(self.max_digits - self.decimal_places))
         return value
 
 DEFAULT_DATE_INPUT_FORMATS = (
@@ -288,7 +289,7 @@
                 return datetime.date(*time.strptime(value, format)[:3])
             except ValueError:
                 continue
-        raise ValidationError(ugettext(u'Enter a valid date.'))
+        raise ValidationError(self.error_messages['invalid'])
 
 DEFAULT_TIME_INPUT_FORMATS = (
     '%H:%M:%S',     # '14:30:59'
@@ -319,7 +320,7 @@
                 return datetime.time(*time.strptime(value, format)[3:6])
             except ValueError:
                 continue
-        raise ValidationError(ugettext(u'Enter a valid time.'))
+        raise ValidationError(self.error_messages['invalid'])
 
 DEFAULT_DATETIME_INPUT_FORMATS = (
     '%Y-%m-%d %H:%M:%S',     # '2006-10-25 14:30:59'
@@ -359,14 +360,14 @@
             # Input comes from a SplitDateTimeWidget, for example. So, it's two
             # components: date and time.
             if len(value) != 2:
-                raise ValidationError(ugettext(u'Enter a valid date/time.'))
+                raise ValidationError(self.error_messages['invalid'])
             value = '%s %s' % tuple(value)
         for format in self.input_formats:
             try:
                 return datetime.datetime(*time.strptime(value, format)[:6])
             except ValueError:
                 continue
-        raise ValidationError(ugettext(u'Enter a valid date/time.'))
+        raise ValidationError(self.error_messages['invalid'])
 
 class RegexField(CharField):
     def __init__(self, regex, max_length=None, min_length=None, 
error_message=None, *args, **kwargs):
@@ -375,11 +376,15 @@
         error_message is an optional error message to use, if
         'Enter a valid value' is too generic for you.
         """
+        # error_message is just kept for backwards compatibility:
+        if error_message:
+            error_messages = kwargs.get('error_messages') or {}
+            error_messages['invalid'] = error_message
+            kwargs['error_messages'] = error_messages
         super(RegexField, self).__init__(max_length, min_length, *args, 
**kwargs)
         if isinstance(regex, basestring):
             regex = re.compile(regex)
         self.regex = regex
-        self.error_message = error_message or ugettext(u'Enter a valid value.')
 
     def clean(self, value):
         """
@@ -390,7 +395,7 @@
         if value == u'':
             return value
         if not self.regex.search(value):
-            raise ValidationError(self.error_message)
+            raise ValidationError(self.error_messages['invalid'])
         return value
 
 email_re = re.compile(
@@ -404,8 +409,8 @@
     }
 
     def __init__(self, max_length=None, min_length=None, *args, **kwargs):
-        RegexField.__init__(self, email_re, max_length, min_length,
-            ugettext(u'Enter a valid e-mail address.'), *args, **kwargs)
+        RegexField.__init__(self, email_re, max_length, min_length, *args,
+                            **kwargs)
 
 try:
     from django.conf import settings
@@ -445,11 +450,11 @@
         try:
             f = UploadedFile(data['filename'], data['content'])
         except TypeError:
-            raise ValidationError(ugettext(u"No file was submitted. Check the 
encoding type on the form."))
+            raise ValidationError(self.error_messages['invalid'])
         except KeyError:
-            raise ValidationError(ugettext(u"No file was submitted."))
+            raise ValidationError(self.error_messages['missing'])
         if not f.content:
-            raise ValidationError(ugettext(u"The submitted file is empty."))
+            raise ValidationError(self.error_messages['empty'])
         return f
 
 class ImageField(FileField):
@@ -477,7 +482,7 @@
             trial_image = Image.open(StringIO(f.content))
             trial_image.verify()
         except Exception: # Python Imaging Library doesn't recognize it as an 
image
-            raise ValidationError(ugettext(u"Upload a valid image. The file 
you uploaded was either not an image or a corrupted image."))
+            raise ValidationError(self.error_messages['invalid_image'])
         return f
 
 url_re = re.compile(
@@ -496,7 +501,8 @@
 
     def __init__(self, max_length=None, min_length=None, verify_exists=False,
             validator_user_agent=URL_VALIDATOR_USER_AGENT, *args, **kwargs):
-        super(URLField, self).__init__(url_re, max_length, min_length, 
ugettext(u'Enter a valid URL.'), *args, **kwargs)
+        super(URLField, self).__init__(url_re, max_length, min_length, *args,
+                                       **kwargs)
         self.verify_exists = verify_exists
         self.user_agent = validator_user_agent
 
@@ -521,9 +527,9 @@
                 req = urllib2.Request(value, None, headers)
                 u = urllib2.urlopen(req)
             except ValueError:
-                raise ValidationError(ugettext(u'Enter a valid URL.'))
+                raise ValidationError(self.error_messages['invalid'])
             except: # urllib2.URLError, httplib.InvalidURL, etc.
-                raise ValidationError(ugettext(u'This URL appears to be a 
broken link.'))
+                raise ValidationError(self.error_messages['invalid_link'])
         return value
 
 class BooleanField(Field):
@@ -583,7 +589,7 @@
             return value
         valid_values = set([smart_unicode(k) for k, v in self.choices])
         if value not in valid_values:
-            raise ValidationError(ugettext(u'Select a valid choice. That 
choice is not one of the available choices.'))
+            raise ValidationError(self.error_messages['invalid_choice'] % 
{'value': value})
         return value
 
 class MultipleChoiceField(ChoiceField):
@@ -599,17 +605,17 @@
         Validates that the input is a list or tuple.
         """
         if self.required and not value:
-            raise ValidationError(ugettext(u'This field is required.'))
+            raise ValidationError(self.error_messages['required'])
         elif not self.required and not value:
             return []
         if not isinstance(value, (list, tuple)):
-            raise ValidationError(ugettext(u'Enter a list of values.'))
+            raise ValidationError(self.error_messages['invalid_list'])
         new_value = [smart_unicode(val) for val in value]
         # Validate that each value in the value list is in self.choices.
         valid_values = set([smart_unicode(k) for k, v in self.choices])
         for val in new_value:
             if val not in valid_values:
-                raise ValidationError(ugettext(u'Select a valid choice. %s is 
not one of the available choices.') % val)
+                raise ValidationError(self.error_messages['invalid_choice'] % 
{'value': val})
         return new_value
 
 class ComboField(Field):
@@ -679,18 +685,18 @@
         if not value or isinstance(value, (list, tuple)):
             if not value or not [v for v in value if v not in EMPTY_VALUES]:
                 if self.required:
-                    raise ValidationError(ugettext(u'This field is required.'))
+                    raise ValidationError(self.error_messages['required'])
                 else:
                     return self.compress([])
         else:
-            raise ValidationError(ugettext(u'Enter a list of values.'))
+            raise ValidationError(self.error_messages['invalid'])
         for i, field in enumerate(self.fields):
             try:
                 field_value = value[i]
             except IndexError:
                 field_value = None
             if self.required and field_value in EMPTY_VALUES:
-                raise ValidationError(ugettext(u'This field is required.'))
+                raise ValidationError(self.error_messages['required'])
             try:
                 clean_data.append(field.clean(field_value))
             except ValidationError, e:
@@ -720,7 +726,13 @@
     }
 
     def __init__(self, *args, **kwargs):
-        fields = (DateField(), TimeField())
+        errors = self.default_error_messages.copy()
+        if 'error_messages' in kwargs:
+            errors.update(kwargs['error_messages'])
+        fields = (
+            DateField(error_messages={'invalid': errors['invalid_date']}),
+            TimeField(error_messages={'invalid': errors['invalid_time']}),
+        )
         super(SplitDateTimeField, self).__init__(fields, *args, **kwargs)
 
     def compress(self, data_list):
@@ -728,9 +740,9 @@
             # Raise a validation error if time or date is empty
             # (possible if SplitDateTimeField has required=False).
             if data_list[0] in EMPTY_VALUES:
-                raise ValidationError(ugettext(u'Enter a valid date.'))
+                raise ValidationError(self.error_messages['invalid_date'])
             if data_list[1] in EMPTY_VALUES:
-                raise ValidationError(ugettext(u'Enter a valid time.'))
+                raise ValidationError(self.error_messages['invalid_time'])
             return datetime.datetime.combine(*data_list)
         return None
 
@@ -742,7 +754,4 @@
     }
 
     def __init__(self, *args, **kwargs):
-        RegexField.__init__(self, ipv4_re,
-                            error_message=ugettext(u'Enter a valid IPv4 
address.'),
-                            *args, **kwargs)
-
+        super(IPAddressField, self).__init__(ipv4_re, *args, **kwargs)

Modified: django/branches/queryset-refactor/django/newforms/util.py
===================================================================
--- django/branches/queryset-refactor/django/newforms/util.py   2007-11-18 
07:19:11 UTC (rev 6692)
+++ django/branches/queryset-refactor/django/newforms/util.py   2007-11-18 
12:07:25 UTC (rev 6693)
@@ -46,13 +46,18 @@
         if not self: return u''
         return u'\n'.join([u'* %s' % force_unicode(e) for e in self])
 
+    def __repr__(self):
+        return repr([force_unicode(e) for e in self])
+
 class ValidationError(Exception):
     def __init__(self, message):
-        "ValidationError can be passed a string or a list."
+        """
+        ValidationError can be passed any object that can be printed (usually
+        a string) or a list of objects.
+        """
         if isinstance(message, list):
             self.messages = ErrorList([smart_unicode(msg) for msg in message])
         else:
-            assert isinstance(message, (basestring, Promise)), ("%s should be 
a basestring or lazy translation" % repr(message))
             message = smart_unicode(message)
             self.messages = ErrorList([message])
 
@@ -62,4 +67,3 @@
         # AttributeError: ValidationError instance has no attribute 'args'
         # See http://www.python.org/doc/current/tut/node10.html#handling
         return repr(self.messages)
-

Modified: django/branches/queryset-refactor/django/templatetags/cache.py
===================================================================
--- django/branches/queryset-refactor/django/templatetags/cache.py      
2007-11-18 07:19:11 UTC (rev 6692)
+++ django/branches/queryset-refactor/django/templatetags/cache.py      
2007-11-18 12:07:25 UTC (rev 6693)
@@ -1,57 +1,57 @@
-from django.template import Library, Node, TemplateSyntaxError
-from django.template import resolve_variable
-from django.core.cache import cache
-from django.utils.encoding import force_unicode
-
-register = Library()
-
-class CacheNode(Node):
-    def __init__(self, nodelist, expire_time, fragment_name, vary_on):
-        self.nodelist = nodelist
-        self.expire_time = expire_time
-        self.fragment_name = fragment_name
-        self.vary_on = vary_on
-
-    def render(self, context):
-        # Build a unicode key for this fragment and all vary-on's.
-        cache_key = u':'.join([self.fragment_name] + \
-            [force_unicode(resolve_variable(var, context)) for var in 
self.vary_on])
-        value = cache.get(cache_key)
-        if value is None:
-            value = self.nodelist.render(context)
-            cache.set(cache_key, value, self.expire_time)
-        return value
-
-def do_cache(parser, token):
-    """
-    This will cache the contents of a template fragment for a given amount
-    of time.
-
-    Usage::
-
-        {% load cache %}
-        {% cache [expire_time] [fragment_name] %}
-            .. some expensive processing ..
-        {% endcache %}
-
-    This tag also supports varying by a list of arguments::
-
-        {% load cache %}
-        {% cache [expire_time] [fragment_name] [var1] [var2] .. %}
-            .. some expensive processing ..
-        {% endcache %}
-
-    Each unique set of arguments will result in a unique cache entry.
-    """
-    nodelist = parser.parse(('endcache',))
-    parser.delete_first_token()
-    tokens = token.contents.split()
-    if len(tokens) < 3:
-        raise TemplateSyntaxError(u"'%r' tag requires at least 2 arguments." % 
tokens[0])
-    try:
-        expire_time = int(tokens[1])
-    except ValueError:
-        raise TemplateSyntaxError(u"First argument to '%r' must be an integer 
(got '%s')." % (tokens[0], tokens[1]))
-    return CacheNode(nodelist, expire_time, tokens[2], tokens[3:])
-
-register.tag('cache', do_cache)
+from django.template import Library, Node, TemplateSyntaxError
+from django.template import resolve_variable
+from django.core.cache import cache
+from django.utils.encoding import force_unicode
+
+register = Library()
+
+class CacheNode(Node):
+    def __init__(self, nodelist, expire_time, fragment_name, vary_on):
+        self.nodelist = nodelist
+        self.expire_time = expire_time
+        self.fragment_name = fragment_name
+        self.vary_on = vary_on
+
+    def render(self, context):
+        # Build a unicode key for this fragment and all vary-on's.
+        cache_key = u':'.join([self.fragment_name] + \
+            [force_unicode(resolve_variable(var, context)) for var in 
self.vary_on])
+        value = cache.get(cache_key)
+        if value is None:
+            value = self.nodelist.render(context)
+            cache.set(cache_key, value, self.expire_time)
+        return value
+
+def do_cache(parser, token):
+    """
+    This will cache the contents of a template fragment for a given amount
+    of time.
+
+    Usage::
+
+        {% load cache %}
+        {% cache [expire_time] [fragment_name] %}
+            .. some expensive processing ..
+        {% endcache %}
+
+    This tag also supports varying by a list of arguments::
+
+        {% load cache %}
+        {% cache [expire_time] [fragment_name] [var1] [var2] .. %}
+            .. some expensive processing ..
+        {% endcache %}
+
+    Each unique set of arguments will result in a unique cache entry.
+    """
+    nodelist = parser.parse(('endcache',))
+    parser.delete_first_token()
+    tokens = token.contents.split()
+    if len(tokens) < 3:
+        raise TemplateSyntaxError(u"'%r' tag requires at least 2 arguments." % 
tokens[0])
+    try:
+        expire_time = int(tokens[1])
+    except ValueError:
+        raise TemplateSyntaxError(u"First argument to '%r' must be an integer 
(got '%s')." % (tokens[0], tokens[1]))
+    return CacheNode(nodelist, expire_time, tokens[2], tokens[3:])
+
+register.tag('cache', do_cache)

Modified: django/branches/queryset-refactor/django/test/testcases.py
===================================================================
--- django/branches/queryset-refactor/django/test/testcases.py  2007-11-18 
07:19:11 UTC (rev 6692)
+++ django/branches/queryset-refactor/django/test/testcases.py  2007-11-18 
12:07:25 UTC (rev 6693)
@@ -150,7 +150,7 @@
                                         " context %d does not contain the"
                                         " error '%s' (actual errors: %s)" %
                                             (field, form, i, err,
-                                             list(field_errors)))
+                                             repr(field_errors)))
                     elif field in context[form].fields:
                         self.fail("The field '%s' on form '%s' in context %d"
                                   " contains no errors" % (field, form, i))

Modified: django/branches/queryset-refactor/docs/newforms.txt
===================================================================
--- django/branches/queryset-refactor/docs/newforms.txt 2007-11-18 07:19:11 UTC 
(rev 6692)
+++ django/branches/queryset-refactor/docs/newforms.txt 2007-11-18 12:07:25 UTC 
(rev 6693)
@@ -1078,6 +1078,30 @@
     <p>Sender: <input type="text" name="sender" /> A valid e-mail address, 
please.</p>
     <p>Cc myself: <input type="checkbox" name="cc_myself" /></p>
 
+``error_messages``
+~~~~~~~~~~~~~~~~~~
+
+**New in Django development version**
+
+The ``error_messages`` argument lets you override the default messages which 
the
+field will raise. Pass in a dictionary with keys matching the error messages 
you
+want to override. For example::
+
+    >>> generic = forms.CharField()
+    >>> generic.clean('')
+    Traceback (most recent call last):
+      ...
+    ValidationError: [u'This field is required.']
+
+    >>> name = forms.CharField(error_messages={'required': 'Please enter your 
name'})
+    >>> name.clean('')
+    Traceback (most recent call last):
+      ...
+    ValidationError: [u'Please enter your name']
+
+In the `built-in Field classes`_ section below, each Field defines the error
+message keys it uses.  
+
 Dynamic initial values
 ----------------------
 
@@ -1143,6 +1167,7 @@
     * Normalizes to: A Python ``True`` or ``False`` value.
     * Validates that the check box is checked (i.e. the value is ``True``) if
       the field has ``required=True``.
+    * Error message keys: ``required``
 
 **New in Django development version:** The empty value for a ``CheckboxInput``
 (and hence the standard ``BooleanField``) has changed to return ``False``
@@ -1162,6 +1187,7 @@
     * Normalizes to: A Unicode object.
     * Validates ``max_length`` or ``min_length``, if they are provided.
       Otherwise, all inputs are valid.
+    * Error message keys: ``required``, ``max_length``, ``min_length``
 
 Has two optional arguments for validation, ``max_length`` and ``min_length``.
 If provided, these arguments ensure that the string is at most or at least the
@@ -1174,6 +1200,7 @@
     * Empty value: ``''`` (an empty string)
     * Normalizes to: A Unicode object.
     * Validates that the given value exists in the list of choices.
+    * Error message keys: ``required``, ``invalid_choice``
 
 Takes one extra argument, ``choices``, which is an iterable (e.g., a list or
 tuple) of 2-tuples to use as choices for this field.
@@ -1186,6 +1213,7 @@
     * Normalizes to: A Python ``datetime.date`` object.
     * Validates that the given value is either a ``datetime.date``,
       ``datetime.datetime`` or string formatted in a particular date format.
+    * Error message keys: ``required``, ``invalid``
 
 Takes one optional argument, ``input_formats``, which is a list of formats used
 to attempt to convert a string to a valid ``datetime.date`` object.
@@ -1206,6 +1234,7 @@
     * Normalizes to: A Python ``datetime.datetime`` object.
     * Validates that the given value is either a ``datetime.datetime``,
       ``datetime.date`` or string formatted in a particular datetime format.
+    * Error message keys: ``required``, ``invalid``
 
 Takes one optional argument, ``input_formats``, which is a list of formats used
 to attempt to convert a string to a valid ``datetime.datetime`` object.
@@ -1235,6 +1264,9 @@
     * Normalizes to: A Python ``decimal``.
     * Validates that the given value is a decimal. Leading and trailing
       whitespace is ignored.
+    * Error message keys: ``required``, ``invalid``, ``max_value``,
+      ``min_value``, ``max_digits``, ``max_decimal_places``,
+      ``max_whole_digits``
 
 Takes four optional arguments: ``max_value``, ``min_value``, ``max_digits``,
 and ``decimal_places``. The first two define the limits for the fields value.
@@ -1251,6 +1283,7 @@
     * Normalizes to: A Unicode object.
     * Validates that the given value is a valid e-mail address, using a
       moderately complex regular expression.
+    * Error message keys: ``required``, ``invalid``
 
 Has two optional arguments for validation, ``max_length`` and ``min_length``.
 If provided, these arguments ensure that the string is at most or at least the
@@ -1266,6 +1299,7 @@
     * Normalizes to: An ``UploadedFile`` object that wraps the file content
       and file name into a single object.
     * Validates that non-empty file data has been bound to the form.
+    * Error message keys: ``required``, ``invalid``, ``missing``, ``empty``
 
 An ``UploadedFile`` object has two attributes:
 
@@ -1296,6 +1330,8 @@
       and file name into a single object.
     * Validates that file data has been bound to the form, and that the
       file is of an image format understood by PIL.
+    * Error message keys: ``required``, ``invalid``, ``missing``, ``empty``,
+      ``invalid_image``
 
 Using an ImageField requires that the `Python Imaging Library`_ is installed.
 
@@ -1312,6 +1348,8 @@
     * Normalizes to: A Python integer or long integer.
     * Validates that the given value is an integer. Leading and trailing
       whitespace is allowed, as in Python's ``int()`` function.
+    * Error message keys: ``required``, ``invalid``, ``max_value``,
+      ``min_value``
 
 Takes two optional arguments for validation, ``max_value`` and ``min_value``.
 These control the range of values permitted in the field.
@@ -1324,6 +1362,7 @@
     * Normalizes to: A Unicode object.
     * Validates that the given value is a valid IPv4 address, using a regular
       expression.
+    * Error message keys: ``required``, ``invalid``
 
 ``MultipleChoiceField``
 ~~~~~~~~~~~~~~~~~~~~~~~
@@ -1333,6 +1372,7 @@
     * Normalizes to: A list of Unicode objects.
     * Validates that every value in the given list of values exists in the list
       of choices.
+    * Error message keys: ``required``, ``invalid_choice``, ``invalid_list``
 
 Takes one extra argument, ``choices``, which is an iterable (e.g., a list or
 tuple) of 2-tuples to use as choices for this field.
@@ -1353,6 +1393,7 @@
     * Normalizes to: A Unicode object.
     * Validates that the given value matches against a certain regular
       expression.
+    * Error message keys: ``required``, ``invalid``
 
 Takes one required argument, ``regex``, which is a regular expression specified
 either as a string or a compiled regular expression object.
@@ -1364,11 +1405,13 @@
     ======================  
=====================================================
     ``max_length``          Ensures the string has at most this many 
characters.
     ``min_length``          Ensures the string has at least this many 
characters.
-    ``error_message``       Error message to return for failed validation. If 
no
-                            message is provided, a generic error message will 
be
-                            used.
     ======================  
=====================================================
 
+The optional argument ``error_message`` is also accepted for backwards
+compatibility. The preferred way to provide an error message is to use the
+``error_messages`` argument, passing a dictionary with ``'invalid'`` as a key
+and the error message as the value. 
+
 ``TimeField``
 ~~~~~~~~~~~~~
 
@@ -1377,6 +1420,7 @@
     * Normalizes to: A Python ``datetime.time`` object.
     * Validates that the given value is either a ``datetime.time`` or string
       formatted in a particular time format.
+    * Error message keys: ``required``, ``invalid``
 
 Takes one optional argument, ``input_formats``, which is a list of formats used
 to attempt to convert a string to a valid ``datetime.time`` object.
@@ -1393,6 +1437,7 @@
     * Empty value: ``''`` (an empty string)
     * Normalizes to: A Unicode object.
     * Validates that the given value is a valid URL.
+    * Error message keys: ``required``, ``invalid``, ``invalid_link``
 
 Takes the following optional arguments:
 


--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to