Index: django/newforms/forms.py
===================================================================
--- django/newforms/forms.py	(revision 4193)
+++ django/newforms/forms.py	(working copy)
@@ -36,10 +36,11 @@
     "A collection of Fields, plus their associated data."
     __metaclass__ = DeclarativeFieldsMetaclass
 
-    def __init__(self, data=None, auto_id='id_%s'): # TODO: prefix stuff
+    def __init__(self, data=None, auto_id='id_%s', prefix=None):
         self.ignore_errors = data is None
         self.data = data or {}
         self.auto_id = auto_id
+        self.prefix = prefix
         self.clean_data = None # Stores the data after clean() has been called.
         self.__errors = None # Stores the errors after clean() has been called.
 
@@ -48,6 +49,9 @@
 
     def __iter__(self):
         for name, field in self.fields.items():
+            # TODO: This prefix code probably shouldn't be in so many places.
+            if self.prefix:
+                name = "%s.%s" % (self.prefix, name)
             yield BoundField(self, field, name)
 
     def __getitem__(self, name):
@@ -56,6 +60,9 @@
             field = self.fields[name]
         except KeyError:
             raise KeyError('Key %r not found in Form' % name)
+        # TODO: This prefix code probably shouldn't be in so many places.
+        if self.prefix:
+            name = "%s.%s" % (self.prefix, name)
         return BoundField(self, field, name)
 
     def _errors(self):
@@ -77,6 +84,9 @@
         top_errors = self.non_field_errors() # Errors that should be displayed above all fields.
         output, hidden_fields = [], []
         for name, field in self.fields.items():
+            # TODO: This prefix code probably shouldn't be in so many places.
+            if self.prefix:
+                name = "%s.%s" % (self.prefix, name)
             bf = BoundField(self, field, name)
             bf_errors = bf.errors # Cache in local variable.
             if bf.is_hidden:
@@ -129,10 +139,15 @@
             self.__errors = errors
             return
         for name, field in self.fields.items():
+            # TODO: This prefix code probably shouldn't be in so many places.
+            if self.prefix:
+                prefixed_name = "%s.%s" % (self.prefix, name)
+            else:
+                prefixed_name = name
             # value_from_datadict() gets the data from the dictionary.
             # Each widget type knows how to retrieve its own data, because some
             # widgets split data over several HTML fields.
-            value = field.widget.value_from_datadict(self.data, name)
+            value = field.widget.value_from_datadict(self.data, prefixed_name)
             try:
                 value = field.clean(value)
                 self.clean_data[name] = value
Index: tests/regressiontests/forms/tests.py
===================================================================
--- tests/regressiontests/forms/tests.py	(revision 4193)
+++ tests/regressiontests/forms/tests.py	(working copy)
@@ -1924,6 +1924,64 @@
 <li>Password1: <input type="password" name="password1" /></li>
 <li>Password (again): <input type="password" name="password2" /></li>
 
+# Forms with prefixes #########################################################
+
+Sometimes you'd like to have multiple forms display on the same html page, or
+maybe just multiple copies of the same form. We can accomplish this with form
+prefixes.
+
+>>> class Person(Form):
+...     first_name = CharField()
+...     last_name = CharField()
+...     birthday = DateField()
+
+Pass a dictionary to a Form's __init__(), but also pass in the keyword argument
+'prefix'. This value will be prepended to each html form field name. One way to 
+think about this is "namespaces for html forms". Notice that in the data 
+argument, each field's key has the prefix, in this case 'person1', prepended 
+to the actual field name.
+>>> data = {
+...     'person1.first_name': u'John',
+...     'person1.last_name': u'Lennon',
+...     'person1.birthday': u'1940-10-9'
+... }
+>>> p = Person(data, prefix='person1')
+>>> print p['first_name']
+<input type="text" name="person1.first_name" value="John" id="id_person1.first_name" />
+>>> print p['last_name']
+<input type="text" name="person1.last_name" value="Lennon" id="id_person1.last_name" />
+>>> print p['birthday']
+<input type="text" name="person1.birthday" value="1940-10-9" id="id_person1.birthday" />
+>>> p.errors
+{}
+>>> p.is_valid()
+True
+
+This is pretty unremarkable in and of itself, but let's create some data that
+contains info for two different people.
+>>> data = {
+...     'person1.first_name': u'John', 
+...     'person1.last_name': u'Lennon', 
+...     'person1.birthday': u'1940-10-9',
+...     'person2.first_name': u'Jim', 
+...     'person2.last_name': u'Morrison', 
+...     'person2.birthday': u'1943-12-8'
+... }
+
+If we use the correct prefix argument, we can create two different forms that
+will only use and validate the data for fields with a matching prefix.
+>>> p1 = Person(data, prefix='person1')
+>>> p1.is_valid()
+True
+>>> p1.clean_data
+{'first_name': u'John', 'last_name': u'Lennon', 'birthday': datetime.date(1940, 10, 9)}
+
+>>> p2 = Person(data, prefix='person2')
+>>> p2.is_valid()
+True
+>>> p2.clean_data
+{'first_name': u'Jim', 'last_name': u'Morrison', 'birthday': datetime.date(1943, 12, 8)}
+
 # Basic form processing in a view #############################################
 
 >>> from django.template import Template, Context
