Index: django/forms/models.py
===================================================================
--- django/forms/models.py	(revision 8691)
+++ django/forms/models.py	(working copy)
@@ -222,13 +222,23 @@
 
 def modelform_factory(model, form=ModelForm, fields=None, exclude=None,
                        formfield_callback=lambda f: f.formfield()):
-    # HACK: we should be able to construct a ModelForm without creating
-    # and passing in a temporary inner class
-    class Meta:
-        pass
-    setattr(Meta, 'model', model)
-    setattr(Meta, 'fields', fields)
-    setattr(Meta, 'exclude', exclude)
+    import types
+    bases = ()
+    if hasattr(form, 'Meta'):
+        bases = (form.Meta, )
+    Meta = types.ClassType('Meta', bases, {})
+
+    form_model = getattr(Meta, 'model', None)
+    if form_model:
+        if form_model != model:
+            raise Exception('model %s does not match model %s for ModelForm %s' % 
+                (model, form_model, form))
+    else:
+        setattr(Meta, 'model', model)
+
+    if fields: setattr(Meta, 'fields', fields)
+    if exclude: setattr(Meta, 'exclude', exclude)
+
     class_name = model.__name__ + 'Form'
     return ModelFormMetaclass(class_name, (form,), {'Meta': Meta,
                               'formfield_callback': formfield_callback})
@@ -244,78 +254,51 @@
 
     def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
                  queryset=None, **kwargs):
-        self.queryset = queryset
-        defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix}
+        self._queryset = queryset
         if self.max_num > 0:
-            qs = self.get_queryset()[:self.max_num]
-        else:
-            qs = self.get_queryset()
-        defaults['initial'] = [model_to_dict(obj) for obj in qs]
+            self._queryset = self.get_queryset()[:self.max_num]        
+        defaults = {'data': data, 'files': files, 'auto_id': auto_id, 'prefix': prefix}
+        defaults['initial'] = [model_to_dict(obj) for obj in self.get_queryset()]
         defaults.update(kwargs)
         super(BaseModelFormSet, self).__init__(**defaults)
 
     def get_queryset(self):
-        if self.queryset is not None:
-            return self.queryset
-        return self.model._default_manager.get_query_set()
+        if not self._queryset:
+            self._queryset = self.model._default_manager.get_query_set()
+        return self._queryset
 
-    def save_new(self, form, commit=True):
-        """Saves and returns a new model instance for the given form."""
-        return save_instance(form, self.model(), commit=commit)
-
-    def save_existing(self, form, instance, commit=True):
-        """Saves and returns an existing model instance for the given form."""
-        return save_instance(form, instance, commit=commit)
-
     def save(self, commit=True):
         """Saves model instances for every form, adding and changing instances
         as necessary, and returns the list of instances.
         """
+        self.changed_objects = []
+        self.deleted_objects = []
+        self.new_objects = []
+        saved_instances = []
+
         if not commit:
             self.saved_forms = []
             def save_m2m():
                 for form in self.saved_forms:
                     form.save_m2m()
             self.save_m2m = save_m2m
-        return self.save_existing_objects(commit) + self.save_new_objects(commit)
 
-    def save_existing_objects(self, commit=True):
-        self.changed_objects = []
-        self.deleted_objects = []
-        if not self.get_queryset():
-            return []
-
-        # Put the objects from self.get_queryset into a dict so they are easy to lookup by pk
-        existing_objects = {}
-        for obj in self.get_queryset():
-            existing_objects[obj.pk] = obj
-        saved_instances = []
-        for form in self.initial_forms:
-            obj = existing_objects[form.cleaned_data[self.model._meta.pk.attname]]
-            if self.can_delete and form.cleaned_data[DELETION_FIELD_NAME]:
-                self.deleted_objects.append(obj)
-                obj.delete()
-            else:
-                if form.changed_data:
-                    self.changed_objects.append((obj, form.changed_data))
-                    saved_instances.append(self.save_existing(form, obj, commit=commit))
-                    if not commit:
-                        self.saved_forms.append(form)
-        return saved_instances
-
-    def save_new_objects(self, commit=True):
-        self.new_objects = []
-        for form in self.extra_forms:
+        for form in self.forms:
             if not form.has_changed():
                 continue
-            # If someone has marked an add form for deletion, don't save the
-            # object.
             if self.can_delete and form.cleaned_data[DELETION_FIELD_NAME]:
-                continue
-            self.new_objects.append(self.save_new(form, commit=commit))
-            if not commit:
-                self.saved_forms.append(form)
-        return self.new_objects
+                if form.instance and form.instance.pk:
+                    self.deleted_objects.append(form.instance)
+                    form.instance.delete()
+            else:
+                if form.instance.pk:
+                    self.changed_objects.append((form.instance, form.changed_data))
+                    saved_instances.append(form.save(commit=commit))
+                else:
+                    self.new_objects.append(form.save(commit=commit))
+                if not commit:
+                    self.saved_forms.append(form)
+        return saved_instances + self.new_objects
 
     def add_fields(self, form, index):
         """Add a hidden field for the object's primary key."""
@@ -324,6 +307,14 @@
             form.fields[self._pk_field_name] = IntegerField(required=False, widget=HiddenInput)
         super(BaseModelFormSet, self).add_fields(form, index)
 
+    def _construct_form(self, i, **kwargs):
+        defaults = {}
+        if i < self._initial_form_count:
+            defaults['instance'] = self.get_queryset()[i]
+        defaults.update(kwargs)
+        return super(BaseModelFormSet, self)._construct_form(i, **defaults)
+
+
 def modelformset_factory(model, form=ModelForm, formfield_callback=lambda f: f.formfield(),
                          formset=BaseModelFormSet,
                          extra=1, can_delete=False, can_order=False,
@@ -358,18 +349,23 @@
             self._initial_form_count = 0
         super(BaseInlineFormSet, self)._construct_forms()
 
+    def _construct_form(self, i, **kwargs):
+        defaults = {}
+        if i >= self._initial_form_count and self.instance:
+            defaults['instance'] = self.model(**{self.fk.get_attname(): self.instance.pk})
+        defaults.update(kwargs)
+        return super(BaseInlineFormSet, self)._construct_form(i, **defaults)
+
     def get_queryset(self):
         """
         Returns this FormSet's queryset, but restricted to children of
         self.instance
         """
-        kwargs = {self.fk.name: self.instance}
-        return self.model._default_manager.filter(**kwargs)
+        if not self._queryset:
+            kwargs = {self.fk.name: self.instance}
+            self._queryset = self.model._default_manager.filter(**kwargs)
+        return self._queryset
 
-    def save_new(self, form, commit=True):
-        kwargs = {self.fk.get_attname(): self.instance.pk}
-        new_obj = self.model(**kwargs)
-        return save_instance(form, new_obj, commit=commit)
 
 def _get_foreign_key(parent_model, model, fk_name=None):
     """
