Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

newforms-admin: Fixed #7230 -- Added a save_m2m method to BaseModelFo…

…rmSet when commit=False is passed to save. Thanks Books Travis for the original report.

git-svn-id: http://code.djangoproject.com/svn/django/branches/newforms-admin@7930 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 55744e997f92f24608910eecf60509603ec87fec 1 parent a2c7bfc
@brosner brosner authored
View
10 django/newforms/models.py
@@ -331,6 +331,12 @@ def save(self, commit=True):
"""Saves model instances for every form, adding and changing instances
as necessary, and returns the list of 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):
@@ -353,6 +359,8 @@ def save_existing_objects(self, commit=True):
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):
@@ -365,6 +373,8 @@ def save_new_objects(self, commit=True):
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
def add_fields(self, form, index):
View
4 docs/modelforms.txt
@@ -454,7 +454,9 @@ model instances without any database interaction::
... instance.save()
This gives you the ability to attach data to the instances before saving them
-to the database.
+to the database. If your formset contains a ``ManyToManyField`` you will also
+need to make a call to ``formset.save_m2m()`` to ensure the many-to-many
+relationships are saved properly.
Limiting the number of objects editable
---------------------------------------
View
44 tests/modeltests/model_formsets/models.py
@@ -13,9 +13,19 @@ class Book(models.Model):
def __unicode__(self):
return self.title
+class AuthorMeeting(models.Model):
+ name = models.CharField(max_length=100)
+ authors = models.ManyToManyField(Author)
+ created = models.DateField(editable=False)
+
+ def __unicode__(self):
+ return self.name
+
__test__ = {'API_TESTS': """
+>>> from datetime import date
+
>>> from django.newforms.models import modelformset_factory
>>> qs = Author.objects.all()
@@ -162,6 +172,40 @@ def __unicode__(self):
>>> formset.save()
[<Author: Walt Whitman>]
+Test the behavior of commit=False and save_m2m
+
+>>> meeting = AuthorMeeting.objects.create(created=date.today())
+>>> meeting.authors = Author.objects.all()
+
+# create an Author instance to add to the meeting.
+>>> new_author = Author.objects.create(name=u'John Steinbeck')
+
+>>> AuthorMeetingFormSet = modelformset_factory(AuthorMeeting, extra=1, can_delete=True)
+>>> data = {
+... 'form-TOTAL_FORMS': '2', # the number of forms rendered
+... 'form-INITIAL_FORMS': '1', # the number of forms with initial data
+... 'form-MAX_FORMS': '0', # the max number of forms
+... 'form-0-id': '1',
+... 'form-0-name': '2nd Tuesday of the Week Meeting',
+... 'form-0-authors': [2, 1, 3, 4],
+... 'form-1-name': '',
+... 'form-1-authors': '',
+... 'form-1-DELETE': '',
+... }
+>>> formset = AuthorMeetingFormSet(data=data, queryset=AuthorMeeting.objects.all())
+>>> formset.is_valid()
+True
+>>> instances = formset.save(commit=False)
+>>> for instance in instances:
+... instance.created = date.today()
+... instance.save()
+>>> formset.save_m2m()
+>>> instances[0].authors.all()
+[<Author: Charles Baudelaire>, <Author: Walt Whitman>, <Author: Paul Verlaine>, <Author: John Steinbeck>]
+
+# delete the author we created to allow later tests to continue working.
+>>> new_author.delete()
+
Test the behavior of max_num with model formsets. It should properly limit
the queryset to reduce the amount of objects being pulled in when not being
used.
Please sign in to comment.
Something went wrong with that request. Please try again.