mirror of
				https://github.com/django/django.git
				synced 2025-10-26 07:06:08 +00:00 
			
		
		
		
	Fixed #10284 -- ModelFormSet.save(commit=False) no longer deletes objects
Thanks laureline.guerin@ and Wedg.
This commit is contained in:
		| @@ -717,7 +717,8 @@ class BaseModelFormSet(BaseFormSet): | ||||
|             obj = self._existing_object(pk_value) | ||||
|             if form in forms_to_delete: | ||||
|                 self.deleted_objects.append(obj) | ||||
|                 obj.delete() | ||||
|                 if commit: | ||||
|                     obj.delete() | ||||
|                 continue | ||||
|             if form.has_changed(): | ||||
|                 self.changed_objects.append((obj, form.changed_data)) | ||||
|   | ||||
| @@ -94,6 +94,11 @@ Miscellaneous | ||||
|   have a custom :class:`~django.core.files.uploadhandler.FileUploadHandler` | ||||
|   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 | ||||
| ========================== | ||||
|  | ||||
|   | ||||
| @@ -3,7 +3,10 @@ | ||||
| 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 | ||||
| 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 | ||||
| the expected error message appears for the second item. | ||||
|  | ||||
| .. currentmodule:: django.forms.formsets.BaseFormSet | ||||
|  | ||||
| .. method:: total_error_count(self) | ||||
| .. method:: BaseFormSet.total_error_count(self) | ||||
|  | ||||
| .. versionadded:: 1.6 | ||||
|  | ||||
| @@ -353,6 +354,8 @@ formsets and deletion of forms from a formset. | ||||
| ``can_order`` | ||||
| ~~~~~~~~~~~~~ | ||||
|  | ||||
| .. attribute:: BaseFormSet.can_order | ||||
|  | ||||
| Default: ``False`` | ||||
|  | ||||
| Lets you create a formset with the ability to order:: | ||||
| @@ -411,6 +414,8 @@ happen when the user changes these values:: | ||||
| ``can_delete`` | ||||
| ~~~~~~~~~~~~~~ | ||||
|  | ||||
| .. attribute:: BaseFormSet.can_delete | ||||
|  | ||||
| Default: ``False`` | ||||
|  | ||||
| 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>`, | ||||
| model instances for deleted forms will be deleted when you call | ||||
| ``formset.save()``. 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. | ||||
| ``formset.save()``. | ||||
|  | ||||
| .. versionchanged:: 1.7 | ||||
|  | ||||
|     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 | ||||
| ------------------------------------- | ||||
|   | ||||
| @@ -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 | ||||
| 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: | ||||
|  | ||||
| Limiting the number of editable objects | ||||
|   | ||||
| @@ -32,6 +32,9 @@ class DeletionTests(TestCase): | ||||
|             'form-0-DELETE': 'on', | ||||
|         } | ||||
|         formset = PoetFormSet(data, queryset=Poet.objects.all()) | ||||
|         formset.save(commit=False) | ||||
|         self.assertEqual(Poet.objects.count(), 1) | ||||
|  | ||||
|         formset.save() | ||||
|         self.assertTrue(formset.is_valid()) | ||||
|         self.assertEqual(Poet.objects.count(), 0) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user