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})
Теперь мы успешно получили формы набора форм с правильным начальным значением суммы!