Django Formset - 每个表单具有不同初始值的 M2M-through 关系

Django Formset - each form with different initial value from M2M-through relationship

我必须使用由另一个 Class ComponentInModule 实现的 M2M 字段连接的模型,以便我可以在其中添加额外信息,即模块中组件的频率。

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__ 函数中我现在不知道列表中的哪个值是正确的。

有没有办法使用表单集来做到这一点?或者是否还有其他一些我遗漏的选项,如何在 ModelForm 中包含来自 M2M 关系的额外字段?

所以我解决了。我做了一个自定义的 BaseModelFormSet class:

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})

现在已经成功获得了金额初始值正确的表单集的表单!