Fixed #10284 -- ModelFormSet.save(commit=False) no longer deletes objects
Thanks laureline.guerin@ and Wedg.
This commit is contained in:
parent
311c1d2848
commit
65e03a424e
|
@ -717,6 +717,7 @@ 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)
|
||||||
|
if commit:
|
||||||
obj.delete()
|
obj.delete()
|
||||||
continue
|
continue
|
||||||
if form.has_changed():
|
if form.has_changed():
|
||||||
|
|
|
@ -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 @@
|
||||||
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
|
||||||
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.
|
||||||
``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::
|
||||||
``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``::
|
||||||
|
|
||||||
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
|
||||||
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):
|
||||||
'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)
|
||||||
|
|
Loading…
Reference in New Issue