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)

Вернуться на верх