Index: django/utils/datastructures.py
===================================================================
--- django/utils/datastructures.py	(revision 4522)
+++ django/utils/datastructures.py	(working copy)
@@ -43,6 +43,17 @@
                 return True
         return False
 
+class ImmutableDict(dict):
+    "A dictionary whose values cannot be modified."
+    def __setitem__(self, key, value):
+        raise TypeError('This dictionary is immutable')
+
+    def __delitem__(self, key):
+        raise TypeError('This dictionary is immutable')
+
+    def update(self, d):
+        raise TypeError('This dictionary is immutable')
+
 class SortedDict(dict):
     "A dictionary that keeps its keys in the order in which they're inserted."
     def __init__(self, data=None):
Index: django/newforms/forms.py
===================================================================
--- django/newforms/forms.py	(revision 4522)
+++ django/newforms/forms.py	(working copy)
@@ -2,7 +2,7 @@
 Form classes
 """
 
-from django.utils.datastructures import SortedDict, MultiValueDict
+from django.utils.datastructures import SortedDict, MultiValueDict, ImmutableDict
 from django.utils.html import escape
 from fields import Field
 from widgets import TextInput, Textarea, HiddenInput, MultipleHiddenInput
@@ -187,6 +187,8 @@
             errors[NON_FIELD_ERRORS] = e.messages
         if errors:
             delattr(self, 'clean_data')
+        else:
+            self.clean_data = ImmutableDict(self.clean_data) # Make it immutable.
         self.__errors = errors
 
     def clean(self):
Index: tests/regressiontests/forms/tests.py
===================================================================
--- tests/regressiontests/forms/tests.py	(revision 4523)
+++ tests/regressiontests/forms/tests.py	(working copy)
@@ -72,22 +72,6 @@
 >>> w.render('email', 'ŠĐĆŽćžšđ', attrs={'class': 'fun'})
 u'<input type="password" class="fun" value="\u0160\u0110\u0106\u017d\u0107\u017e\u0161\u0111" name="email" />'
 
-The render_value argument lets you specify whether the widget should render
-its value. You may want to do this for security reasons.
->>> w = PasswordInput(render_value=True)
->>> w.render('email', 'secret')
-u'<input type="password" name="email" value="secret" />'
->>> w = PasswordInput(render_value=False)
->>> w.render('email', '')
-u'<input type="password" name="email" />'
->>> w.render('email', None)
-u'<input type="password" name="email" />'
->>> w.render('email', 'secret')
-u'<input type="password" name="email" />'
->>> w = PasswordInput(attrs={'class': 'fun'}, render_value=False)
->>> w.render('email', 'secret')
-u'<input type="password" class="fun" name="email" />'
-
 # HiddenInput Widget ############################################################
 
 >>> w = HiddenInput()
@@ -1745,6 +1729,24 @@
 ...
 KeyError: "Key 'nonexistentfield' not found in Form"
 
+The clean_data dictionary is immutable -- i.e., you cannot add to it, delete
+from it or change its values. Use the copy() method to get a new dictionary
+whose values you can edit.
+>>> p.clean_data['first_name'] = 'foo'
+Traceback (most recent call last):
+...
+TypeError: This dictionary is immutable
+>>> del p.clean_data['first_name']
+Traceback (most recent call last):
+...
+TypeError: This dictionary is immutable
+>>> p.clean_data['new_field_name'] = 'foo'
+Traceback (most recent call last):
+...
+TypeError: This dictionary is immutable
+>>> new_clean_data = p.clean_data.copy()
+>>> new_clean_data['new_field_name'] = 'foo'
+
 >>> for boundfield in p:
 ...     print boundfield
 <input type="text" name="first_name" value="John" id="id_first_name" />
Index: docs/newforms.txt
===================================================================
--- docs/newforms.txt	(revision 4522)
+++ docs/newforms.txt	(working copy)
@@ -273,6 +273,30 @@
     >>> f.clean_data # Doesn't contain extra_field_1, etc.
     {'cc_myself': True, 'message': u'Hi there', 'sender': u'foo@example.com', 'subject': u'hello'}
 
+The ``clean_data`` dictionary is immutable -- you cannot add to it, delete from
+it or change its values. Use the ``copy()`` method, or the ``dict()`` builtin
+function, to get a new dictionary whose values you can edit::
+
+    >>> f.clean_data['subject'] = 'foo'
+    Traceback (most recent call last):
+    ...
+    TypeError: This dictionary is immutable
+    >>> del f.clean_data['subject']
+    Traceback (most recent call last):
+    ...
+    TypeError: This dictionary is immutable
+    >>> f.clean_data['new_field_name'] = 'foo'
+    Traceback (most recent call last):
+    ...
+    TypeError: This dictionary is immutable
+
+    # Method one: copy()
+    >>> new_clean_data = f.clean_data.copy()
+    >>> new_clean_data['new_field_name'] = 'foo' # Now it's mutable.
+
+    # Method two: dict()
+    >>> other_clean_data = dict(f.clean_data, new_field_name='foo')
+
 Behavior of unbound forms
 ~~~~~~~~~~~~~~~~~~~~~~~~~
 
