I have two models with a ManyToMany (M2M) relationship. In order to have extra fields on the M2M Model, I defined a through=
model. I tried setting up a inlineformset_factory, using parent=ChildModel
and model=ParentModel.parent_child.through
as described in this thread pendant to inline formsets for many-to-many relations. But it did not solve my issue.
How can I access (i.e. prepopulate) and update the extra fields of the M2M model, when using formsets?
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,
)
I found a solution, setting up a ModelFormset
on the ChildModel
. For the extra field of the ParentChildModel
, I defined a field in form.py
which I manually populate using the code down below.
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
forms.py
class ChildForm(forms.ModelForm):
extra_field_1 = forms.CharField()
class Meta:
model = ChildModel
fields = '__all__'
ChildFormset = modelformset_factory(ChildModel,
form=ChildForm,
...
)