Django Formset - каждая форма с различным начальным значением из M2M-отношений

Мне нужны модели, которые связаны M2M-полем, реализованным другим классом ComponentInModule, чтобы я мог добавить туда дополнительную информацию, как часто компонент находится в модуле.

class Module(models.Model):
   ...
   component = models.ManyToManyField(Component, through="ComponentInModule")

class Component(models.Model):
   ...

class ComponentInModule(models.Model):
    module = models.ForeignKey(InfrastructureModule, on_delete=models.CASCADE)
    component = models.ForeignKey(InfrastructureComponent, on_delete=models.CASCADE)
    amount = models.IntegerField(default=1)

Теперь я пытаюсь загрузить модуль в виде формы с соответствующими компонентами в виде набора форм.

class ComponentForm(ModelForm):
    amount = IntegerField()
module = InfrastructureModule.objects.get(id=x)
ComponentFormSet = modelformset_factory(Component, form=ComponentForm, extra=0)
component_formset = ComponentFormSet(queryset=module.get_components())

Как вы можете видеть, моя ComponentForm имеет дополнительное поле для суммы. Теперь вопрос в том, как я могу передать значение amount в Formset при создании, чтобы все формы инициализировались правильным значением? С одной формой это не проблема, потому что я могу просто передать значение в функцию __init__ формы и поместить его в поле суммы self.fields["amount"].initial = amount. Я попробовал передать список значений в набор форм с помощью form_kwargs, но тогда у меня возникла проблема, что в функции __init__ я не знаю, какое из значений в списке является правильным в данный момент.

Есть ли способ сделать это с помощью наборов форм? Или есть какой-то другой вариант, который я упускаю, как можно включить дополнительные поля из M2M-отношения в ModelForm?

Так что я решил эту проблему. Я создал пользовательский класс BaseModelFormSet:

class BaseCompFormset(BaseModelFormSet):
    def get_form_kwargs(self, index):
        kwargs = super().get_form_kwargs(index)
        amount = kwargs["amount"][index]
        return {"amount": amount}

Настроил функцию __init__ формы:

 def __init__(self, *args, **kwargs):
        amount = kwargs.pop("amount")
        super(ComponentForm, self).__init__(*args, **kwargs)
        if self.instance:
            self.fields["amount"].initial = amount

И использовал их для создания моей modelformset_factory:

    amounts = [x.amount for x in module.get_components_in_module()]
    ComponentFormSet = modelformset_factory(Component, formset=BaseCompFormset, form=ComponentForm, extra=0)
    component_formset = ComponentFormSet(queryset=module.get_components(), form_kwargs={'amount':amounts})

Теперь мы успешно получили формы набора форм с правильным начальным значением суммы!

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