Kaydet (Commit) 65e03a42 authored tarafından Tim Graham's avatar Tim Graham

Fixed #10284 -- ModelFormSet.save(commit=False) no longer deletes objects

Thanks laureline.guerin@ and Wedg.
üst 311c1d28
...@@ -717,7 +717,8 @@ class BaseModelFormSet(BaseFormSet): ...@@ -717,7 +717,8 @@ class BaseModelFormSet(BaseFormSet):
obj = self._existing_object(pk_value) obj = self._existing_object(pk_value)
if form in forms_to_delete: if form in forms_to_delete:
self.deleted_objects.append(obj) self.deleted_objects.append(obj)
obj.delete() if commit:
obj.delete()
continue continue
if form.has_changed(): if form.has_changed():
self.changed_objects.append((obj, form.changed_data)) self.changed_objects.append((obj, form.changed_data))
......
...@@ -94,6 +94,11 @@ Miscellaneous ...@@ -94,6 +94,11 @@ Miscellaneous
have a custom :class:`~django.core.files.uploadhandler.FileUploadHandler` have a custom :class:`~django.core.files.uploadhandler.FileUploadHandler`
that implements ``new_file()``, be sure it accepts this new parameter. that implements ``new_file()``, be sure it accepts this new parameter.
* :class:`ModelFormSet<django.forms.models.BaseModelFormSet>`'s no longer
delete instances when ``save(commit=False)`` is called. See
:attr:`~django.forms.formsets.BaseFormSet.can_delete` for instructions on how
to manually delete objects from deleted forms.
Features deprecated in 1.7 Features deprecated in 1.7
========================== ==========================
......
...@@ -3,7 +3,10 @@ ...@@ -3,7 +3,10 @@
Formsets Formsets
======== ========
.. class:: django.forms.formsets.BaseFormSet .. module:: django.forms.formsets
:synopsis: An abstraction for working with multiple forms on the same page.
.. class:: BaseFormSet
A formset is a layer of abstraction to work with multiple forms on the same A formset is a layer of abstraction to work with multiple forms on the same
page. It can be best compared to a data grid. Let's say you have the following page. It can be best compared to a data grid. Let's say you have the following
...@@ -164,9 +167,7 @@ As we can see, ``formset.errors`` is a list whose entries correspond to the ...@@ -164,9 +167,7 @@ As we can see, ``formset.errors`` is a list whose entries correspond to the
forms in the formset. Validation was performed for each of the two forms, and forms in the formset. Validation was performed for each of the two forms, and
the expected error message appears for the second item. the expected error message appears for the second item.
.. currentmodule:: django.forms.formsets.BaseFormSet .. method:: BaseFormSet.total_error_count(self)
.. method:: total_error_count(self)
.. versionadded:: 1.6 .. versionadded:: 1.6
...@@ -353,6 +354,8 @@ formsets and deletion of forms from a formset. ...@@ -353,6 +354,8 @@ formsets and deletion of forms from a formset.
``can_order`` ``can_order``
~~~~~~~~~~~~~ ~~~~~~~~~~~~~
.. attribute:: BaseFormSet.can_order
Default: ``False`` Default: ``False``
Lets you create a formset with the ability to order:: Lets you create a formset with the ability to order::
...@@ -411,6 +414,8 @@ happen when the user changes these values:: ...@@ -411,6 +414,8 @@ happen when the user changes these values::
``can_delete`` ``can_delete``
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
.. attribute:: BaseFormSet.can_delete
Default: ``False`` Default: ``False``
Lets you create a formset with the ability to select forms for deletion:: Lets you create a formset with the ability to select forms for deletion::
...@@ -463,10 +468,23 @@ delete fields you can access them with ``deleted_forms``:: ...@@ -463,10 +468,23 @@ delete fields you can access them with ``deleted_forms``::
If you are using a :class:`ModelFormSet<django.forms.models.BaseModelFormSet>`, If you are using a :class:`ModelFormSet<django.forms.models.BaseModelFormSet>`,
model instances for deleted forms will be deleted when you call model instances for deleted forms will be deleted when you call
``formset.save()``. On the other hand, if you are using a plain ``FormSet``, ``formset.save()``.
it's up to you to handle ``formset.deleted_forms``, perhaps in your formset's
``save()`` method, as there's no general notion of what it means to delete a .. versionchanged:: 1.7
form.
If you call ``formset.save(commit=False)``, objects will not be deleted
automatically. You'll need to call ``delete()`` on each of the
:attr:`formset.deleted_objects
<django.forms.models.BaseModelFormSet.deleted_objects>` to actually delete
them::
>>> instances = formset.save(commit=False)
>>> for obj in formset.deleted_objects:
... obj.delete()
On the other hand, if you are using a plain ``FormSet``, it's up to you to
handle ``formset.deleted_forms``, perhaps in your formset's ``save()`` method,
as there's no general notion of what it means to delete a form.
Adding additional fields to a formset Adding additional fields to a formset
------------------------------------- -------------------------------------
......
...@@ -825,6 +825,13 @@ to the database. If your formset contains a ``ManyToManyField``, you'll also ...@@ -825,6 +825,13 @@ to the database. If your formset contains a ``ManyToManyField``, you'll also
need to call ``formset.save_m2m()`` to ensure the many-to-many relationships need to call ``formset.save_m2m()`` to ensure the many-to-many relationships
are saved properly. are saved properly.
After calling ``save()``, your model formset will have three new attributes
containing the formset's changes:
.. attribute:: models.BaseModelFormSet.changed_objects
.. attribute:: models.BaseModelFormSet.deleted_objects
.. attribute:: models.BaseModelFormSet.new_objects
.. _model-formsets-max-num: .. _model-formsets-max-num:
Limiting the number of editable objects Limiting the number of editable objects
......
...@@ -32,6 +32,9 @@ class DeletionTests(TestCase): ...@@ -32,6 +32,9 @@ class DeletionTests(TestCase):
'form-0-DELETE': 'on', 'form-0-DELETE': 'on',
} }
formset = PoetFormSet(data, queryset=Poet.objects.all()) formset = PoetFormSet(data, queryset=Poet.objects.all())
formset.save(commit=False)
self.assertEqual(Poet.objects.count(), 1)
formset.save() formset.save()
self.assertTrue(formset.is_valid()) self.assertTrue(formset.is_valid())
self.assertEqual(Poet.objects.count(), 0) self.assertEqual(Poet.objects.count(), 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment