Index: django/forms/forms.py
===================================================================
--- django/forms/forms.py	(revision 9984)
+++ django/forms/forms.py	(working copy)
@@ -366,12 +366,8 @@
         auto_id = self.auto_id
         if auto_id and 'id' not in attrs and 'id' not in widget.attrs:
             attrs['id'] = auto_id
-        if not self.form.is_bound:
-            data = self.form.initial.get(self.name, self.field.initial)
-            if callable(data):
-                data = data()
-        else:
-            data = self.data
+        # Widgets expect unset data to be None, not empty str.
+        data = self.value
         if not only_initial:
             name = self.html_name
         else:
@@ -401,6 +397,21 @@
         return self.field.widget.value_from_datadict(self.form.data, self.form.files, self.html_name)
     data = property(_data)
 
+    def _value(self):
+        """
+        Returns the value for this BoundField, as rendered in widgets.
+        """
+        if not self.form.is_bound:
+            val = self.form.initial.get(self.name, self.field.initial)
+            if callable(val):
+                val = val()
+        else:
+            val = self.data
+            if val is None:
+                val = ''
+        return val
+    value = property(_value)
+
     def label_tag(self, contents=None, attrs=None):
         """
         Wraps the given contents in a <label>, if the field has an ID attribute.
Index: tests/regressiontests/forms/forms.py
===================================================================
--- tests/regressiontests/forms/forms.py	(revision 9984)
+++ tests/regressiontests/forms/forms.py	(working copy)
@@ -1196,6 +1196,31 @@
 <li>Username: <input type="text" name="username" value="stephane" maxlength="10" /></li>
 <li>Password: <input type="password" name="password" /></li>
 
+# Bound field values ##########################################################
+
+It's possible to get to the value which would be used for rendering the widget
+for a field by using the BoundField's value attribute.
+
+>>> class UserRegistration(Form):
+...    username = CharField(max_length=10, initial='djangonaut')
+...    password = CharField(widget=PasswordInput)
+>>> p = UserRegistration({'password': 'foo'})
+>>> print 'username.value =', p['username'].value
+username.value = 
+>>> print 'username.data = ', p['username'].data
+username.data = None
+>>> print 'password.value =', p['password'].value
+password.value = foo
+>>> print 'password.data =', p['password'].data
+password.data = foo
+
+The value of username is empty because the form is bound -- the value wasn't
+specified, and so is empty. This differs if the form were to be unbound:
+
+>>> p = UserRegistration()
+>>> print p['username'].value
+djangonaut
+
 # Help text ###################################################################
 
 You can specify descriptive text for a field by using the 'help_text' argument
