Index: django/newforms/util.py
===================================================================
--- django/newforms/util.py	(revision 7321)
+++ django/newforms/util.py	(working copy)
@@ -50,11 +50,12 @@
         return repr([force_unicode(e) for e in self])
 
 class ValidationError(Exception):
-    def __init__(self, message):
+    def __init__(self, message, field_name=None):
         """
         ValidationError can be passed any object that can be printed (usually
         a string) or a list of objects.
         """
+        self.field_name = field_name
         if isinstance(message, list):
             self.messages = ErrorList([smart_unicode(msg) for msg in message])
         else:
Index: django/newforms/forms.py
===================================================================
--- django/newforms/forms.py	(revision 7321)
+++ django/newforms/forms.py	(working copy)
@@ -215,7 +215,11 @@
         try:
             self.cleaned_data = self.clean()
         except ValidationError, e:
-            self._errors[NON_FIELD_ERRORS] = e.messages
+            name = e.field_name or NON_FIELD_ERRORS
+            if e.field_name and name in self._errors:
+                self._errors[name] = ErrorList(self._errors[name] + e.messages)
+            else:
+                self._errors[name] = e.messages
         if self._errors:
             delattr(self, 'cleaned_data')
 
Index: tests/regressiontests/forms/forms.py
===================================================================
--- tests/regressiontests/forms/forms.py	(revision 7321)
+++ tests/regressiontests/forms/forms.py	(working copy)
@@ -611,8 +611,11 @@
 
 Another way of doing multiple-field validation is by implementing the
 Form's clean() method. If you do this, any ValidationError raised by that
-method will not be associated with a particular field; it will have a
-special-case association with the field named '__all__'.
+method either will not be associated with a particular field
+and will have a special-case association with the field named '__all__'; 
+or if you specify the invalid field explicitly by passing the 'field_name'
+parameter to the error constructor, it will be associated with the field in
+similar manner to clean_XXX().
 Note that in Form.clean(), you have access to self.cleaned_data, a dictionary of
 all the fields/values that have *not* raised a ValidationError. Also note
 Form.clean() is required to return a dictionary of all clean data.
@@ -653,6 +656,59 @@
 >>> f.cleaned_data
 {'username': u'adrian', 'password1': u'foo', 'password2': u'foo'}
 
+The following is a somewhat contrived example that tests specifying the
+invalid field in clean(). Note that default values in self.cleaned_data.get()
+are neccessary to test if errors are appended correctly to base field errors.
+
+>>> class EmailRegistration(Form):
+...    username = CharField(max_length=10)
+...    email1 = EmailField()
+...    email2 = EmailField()
+...    def clean(self):
+...        email1 = self.cleaned_data.get('email1', 'foo')
+...        email2 = self.cleaned_data.get('email2', 'bar')
+...        if email1 != email2:
+...            raise ValidationError(u'Please make sure the email addresses match.', field_name = 'email2')
+...        return self.cleaned_data
+... 
+>>> f = EmailRegistration(auto_id=False)
+>>> f.errors
+{}
+>>> f = EmailRegistration({}, auto_id=False)
+>>> f.errors
+{'username': [u'This field is required.'], 'email2': [u'This field is required.', u'Please make sure the email addresses match.'], 'email1': [u'This field is required.']}
+>>> print f.as_ul()
+<li><ul class="errorlist"><li>This field is required.</li></ul>Username: <input type="text" name="username" maxlength="10" /></li>
+<li><ul class="errorlist"><li>This field is required.</li></ul>Email1: <input type="text" name="email1" /></li>
+<li><ul class="errorlist"><li>This field is required.</li><li>Please make sure the email addresses match.</li></ul>Email2: <input type="text" name="email2" /></li>
+>>> print f.as_table()
+<tr><th>Username:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="username" maxlength="10" /></td></tr>
+<tr><th>Email1:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="email1" /></td></tr>
+<tr><th>Email2:</th><td><ul class="errorlist"><li>This field is required.</li><li>Please make sure the email addresses match.</li></ul><input type="text" name="email2" /></td></tr>
+>>> f = EmailRegistration({'username': 'adrian', 'email1': 'foo@foo.com', 'email2': 'bar'}, auto_id=False)
+>>> f.errors
+{'email2': [u'Enter a valid e-mail address.', u'Please make sure the email addresses match.']}
+>>> f.as_ul()
+u'<li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li>\n<li>Email1: <input type="text" name="email1" value="foo@foo.com" /></li>\n<li><ul class="errorlist"><li>Enter a valid e-mail address.</li><li>Please make sure the email addresses match.</li></ul>Email2: <input type="text" name="email2" value="bar" /></li>'
+>>> f.as_table()
+u'<tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr>\n<tr><th>Email1:</th><td><input type="text" name="email1" value="foo@foo.com" /></td></tr>\n<tr><th>Email2:</th><td><ul class="errorlist"><li>Enter a valid e-mail address.</li><li>Please make sure the email addresses match.</li></ul><input type="text" name="email2" value="bar" /></td></tr>'
+>>> f = EmailRegistration({'username': 'adrian', 'email1': 'foo@foo.com', 'email2': 'bar@bar.com'}, auto_id=False)
+>>> f.errors
+{'email2': [u'Please make sure the email addresses match.']}
+>>> f.as_ul()
+u'<li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li>\n<li>Email1: <input type="text" name="email1" value="foo@foo.com" /></li>\n<li><ul class="errorlist"><li>Please make sure the email addresses match.</li></ul>Email2: <input type="text" name="email2" value="bar@bar.com" /></li>'
+>>> f.as_table()
+u'<tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr>\n<tr><th>Email1:</th><td><input type="text" name="email1" value="foo@foo.com" /></td></tr>\n<tr><th>Email2:</th><td><ul class="errorlist"><li>Please make sure the email addresses match.</li></ul><input type="text" name="email2" value="bar@bar.com" /></td></tr>'
+>>> f = EmailRegistration({'username': 'adrian', 'email1': 'foo@foo.com', 'email2': 'foo@foo.com'}, auto_id=False)
+>>> f.errors
+{}
+>>> f.as_ul()
+u'<li>Username: <input type="text" name="username" value="adrian" maxlength="10" /></li>\n<li>Email1: <input type="text" name="email1" value="foo@foo.com" /></li>\n<li>Email2: <input type="text" name="email2" value="foo@foo.com" /></li>'
+>>> f.as_table()
+u'<tr><th>Username:</th><td><input type="text" name="username" value="adrian" maxlength="10" /></td></tr>\n<tr><th>Email1:</th><td><input type="text" name="email1" value="foo@foo.com" /></td></tr>\n<tr><th>Email2:</th><td><input type="text" name="email2" value="foo@foo.com" /></td></tr>'
+>>> f.cleaned_data
+{'username': u'adrian', 'email2': u'foo@foo.com', 'email1': u'foo@foo.com'}
+
 # Dynamic construction ########################################################
 
 It's possible to construct a Form dynamically by adding to the self.fields
Index: docs/newforms.txt
===================================================================
--- docs/newforms.txt	(revision 7321)
+++ docs/newforms.txt	(working copy)
@@ -1589,10 +1589,13 @@
       cleaned data if you override this method (by default, ``Form.clean()``
       just returns ``self.cleaned_data``).
 
-      Note that any errors raised by your ``Form.clean()`` override will not
-      be associated with any field in particular. They go into a special
+      Note that by default any errors raised by your ``Form.clean()`` override
+      will not be associated with any field in particular. They go into a special
       "field" (called ``__all__``), which you can access via the
-      ``non_field_errors()`` method if you need to.
+      ``non_field_errors()`` method if you need to. However, if you want to
+      explicitly associate the error with a particular field, you can do so
+      by passing the ``field_name`` parameter to the ``ValidationError``
+      constructor.
 
 These methods are run in the order given above, one field at a time.  That is,
 for each field in the form (in the order they are declared in the form
