Django: Предварительное заполнение дополнительных полей в Formset с помощью модели ManyToMany

У меня есть две модели с отношением ManyToMany (M2M). Для того чтобы иметь дополнительные поля в модели M2M, я определил модель through=. Я попробовал настроить inlineformset_factory, используя parent=ChildModel и model=ParentModel.parent_child.through, как описано в этой теме pendant to inline formsets for many-to-many relations. Но это не решило мою проблему.

Как я могу получить доступ (т.е. предварительно заполнить) и обновить дополнительные поля модели M2M при использовании наборов форм?

models.py

class ParentModel(models.Model):
    name = model.CharField()
    parent_child = model.ManyToManyField(ChildModel, through='ParentChildModel')


class ChildModel(models.Model):
    name = model.CharField()
    

class ParentChildModel(models.Model):
    parent = models.ForeignKey(ParentModel, on_delete=models.CASCADE)
    child = models.ForeignKey(ChildModel, on_delete=models.CASCADE)
    extra_field_1 = models.CharField()

forms.py

class ChildForm(forms.ModelForm):

    class Meta:
        model = ChildModel
        fields = '__all__'



ChildFormset = modelformset_factory(ChildModel,
                                     form=ChildForm,
                                     extra=0,
                                     can_delete=True,
                                     can_order=True,
                                     )

Вам нужно создать набор форм с ParentChildModel и экземпляром ChildModel, а не просто использовать ChildModel, поскольку он не сможет получить доступ к extra_field_1.

В документации предлагается следующая структура inline-formset:

from django.forms import inlineformset_factory

ParentChildFormset = inlineformset_factory(ChildModel, ParentChildModel, ...)
child = ChildModel.objects.get(...)
formset = ParentChildFormset(instance=child)

https://docs.djangoproject.com/en/4.0/topics/forms/modelforms/#inline-formsets

Я нашел решение, установив ModelFormset на ChildModel. Для дополнительного поля я определил поле в form.py, которое я вручную заполняю, используя приведенный ниже код.

views.py

# get instances
parent_instance = Parent.objects.get(id=pk)
parent_children = parent_instance.parent_child.all()
parent_child_instance = ParentChildModel.objects.filter(parent=parent_instance)

# initializing & prepopulate forms
parent_form = ParentForm(request.POST or None, instance=parent_instance)
child_formset = ChildFormset(request.POST or None, queryset=parent_children)
for child_form in child_formset:
    child_form.fields['extra_field_1'].initial = parent_child_instance.get(child=child_form.instance).extra_field_1
Вернуться на верх