Django: Сохраните набор форм с commit=False (в документации ничего не сказано)
С формой все просто, нужно сделать что-то вроде этого:
obj = form.save(commit=False)
obj.foo = 1234
obj.save()
obj.savem_m2m() # If has a ManyToMany field
Теперь для набора форм все гораздо сложнее. Документация не проливает свет: она лишь кратко упоминает сохранение и удаление, не объясняя, каким образом.
Так что я проверил исходный код для formset.save()
:
def save(self, commit=True):
"""
Save model instances for every form, adding and changing instances
as necessary, and return 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)
Итак, если у вас есть commit = False, я предполагаю, что нужно выполнить работу save_existing_objects
и save_new_objects
.
Если посмотреть на эти две функции, то они довольно большие:
def save_existing_objects(self, commit=True):
self.changed_objects = []
self.deleted_objects = []
if not self.initial_forms:
return []
saved_instances = []
forms_to_delete = self.deleted_forms
for form in self.initial_forms:
obj = form.instance
# If the pk is None, it means either:
# 1. The object is an unexpected empty model, created by invalid
# POST data such as an object outside the formset's queryset.
# 2. The object was already deleted from the database.
if obj.pk is None:
continue
if form in forms_to_delete:
self.deleted_objects.append(obj)
self.delete_existing(obj, commit=commit)
elif form.has_changed():
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:
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 self._should_delete_form(form):
continue
self.new_objects.append(self.save_new(form, commit=commit))
if not commit:
self.saved_forms.append(form)
return self.new_objects
Заставляет меня думать, что я что-то упускаю. Каков правильный способ сохранения (и удаления) форм из набора форм с помощью commit=False
?
X Y информация о проблеме
Для справки, проблема, которую я пытаюсь решить, состоит в том, что у меня есть FooForm
, и BarFormSet
. BarFormSet
имеет отношения "многие ко многим" с FooForm
. Они оба создаются одновременно из <form>...</form>
, который имеет обе формы внутри себя. Вот моя процедура сохранения:
bar_formset = self.BarFormSet(request.POST, prefix='foo')
if not foo_form.is_valid() or not bar_formset.is_valid():
# return invalid
with transaction.atomic():
# - Foos
foo = foo_form.save(commit=False)
foo.pancakes = 'yes please'
foo.save()
breakpoint()
# - Bars
foos = bar_formset.save(commit=False)
for obj in bar_formset.deleted_objects:
obj.delete()
for obj in foos:
obj.waffles = 'everyday'
obj.save()
# - Foo - Bar (ManyToMany joining table)
foo.foo_set.add(foos)