Some very curious formset behaviors:
Case 1: this works as expected, i.e. it validates and saves the changes to the form:
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.as_p }}
<input type="submit" value="Submit">
</form>
Case 2: this fails with invalid formset: [{'member_name': ['This field is required.'], 'id': ['This field is required.']}, ... Note that member_name is displayed on the form prior to submission.
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
<table>
{% for form in formset %}
<tr>
<td>{{form.member_name}}</td>
<td style="padding-right: 16px;">{{form.status}}</td>
<td>{{form.comment}}</td>
</tr>
{% endfor %}
</table>
<input type="submit" value="Submit">
</form>
Case 3: this generates two views of the formset; the second one works as expected, but the first one has no effect: no values are changed, though there’s no form errors:
<form method="post">
{% csrf_token %}
{{ formset.management_form }}
{{ formset.as_p }} <hr>
{{ formset.as_p }}
<input type="submit" value="Submit">
</form>
Here’s the model:
class Participant(models.Model):
member_name = models.CharField(max_length=50, null=False, blank=False, help_text="Member name")
event = models.ForeignKey(Event, on_delete=models.CASCADE, null=False, related_name="participants", help_text="The event, e.g. a tennis session or match")
status = models.CharField(max_length=50, choices=StatusChoices, default="Unknown")
comment = models.CharField(max_length=400, blank=True, null=True, default="a comment", help_text="A comment made by a member e.g. about participant in the specific event")
class Meta:
ordering = ['member_name']
And the view:
def formset_test(request, event_id):
event = get_object_or_404(Event, pk=event_id)
ParticipantFormSet = modelformset_factory(Participant, form=ParticipantForm, fields=["id", "member_name", "status", "comment"], extra=0)
formset = ParticipantFormSet()
if request.method == 'POST':
formset = ParticipantFormSet(request.POST)
if formset.is_valid():
formset.save()
else:
print("invalid formset: ", formset.errors)
else:
formset = ParticipantFormSet()
return render(request,'formset_test.html',{'formset': formset, 'event': event})