Is 'initial' the wrong way to populate a formset?

Before I post all the code, this should serve illustrate the problem (or misconception):

all_players = event.participants.all()
print("all_players: ", all_players.count())

only_active_players = all_players.all().filter(status__in=["invited", "confirmed", "waitlisted"]).values()
print("only_active_players: ", only_active_players.count())

formset = ParticipantStatusFormset(initial=only_active_players)
print("forms: ", len(formset))

This reports:

all_players: 3
only_active_players: 2
forms: 3

Do I need to use modelformset_factory instead?

Have you verified what’s in those forms?

Based only upon what you’ve posted here, quoting from Formsets | Django documentation | Django

By default, formset_factory() defines one extra form;

Yes, all the forms in the formset are fully and correctly populated. It’s just that the ‘initial’ param doesn’t seem to do anything.

I’m sorry, I don’t understand.

If:

then what is the issue?

Please be more specific. What are you getting, and what are you expecting to see?

I misspoke. The formset is being populated by all 3 of the event.participants, even though the ‘initial’ argument is a list containing only two of them (i.e., a filtered list).

Ok, there may be a mismatch between the form and the formset. If you’re using a model form, then you should be using a modelformset, and the queryset for initialization.

If you’re using a regular form (not a model form), then you use initial for initial data.

I’m using modelformset_factory: Here’s the form and formset definitions:

class ParticipantStatusForm(forms.ModelForm):
	member_name = forms.CharField(required=True, widget=forms.TextInput())
	status = forms.ChoiceField(required=True, choices=StatusChoices, widget=forms.Select())
	comment = forms.CharField(required=False, widget=forms.Textarea())
	class Meta:
		model = Participant
		fields = ["status","comment","member_name"]

ParticipantStatusFormset = modelformset_factory (
	Participant, 
	form=ParticipantStatusForm,
	fields = ["status","comment","member_name"],
	extra=0, can_delete=False
	)

And the relevant view code:

active_players = event.participants.filter(status__in=["invited", "confirmed", "waitlisted"]).values()
formset = ParticipantStatusFormset(initial=active_players)

If I use queryset instead of initial, the formset gets zero forms:

active_players = event.participants.filter(status__in=["invited", "confirmed", "waitlisted"])
formset = ParticipantStatusFormset(queryset=active_players)

I’m guessing the modelformset_factory (ParticipantStatusFormset) is ignoring the ‘initial’ value and getting all values from the Participant model?

Based upon what you’re showing here, it works for me exactly as expected.

This implies either there’s something you’re not showing that is affecting this, or there’s a data issue.

In addition to the link above, on the same page there’s this in the section Providing initial values:

… However, with model formsets, the initial values only apply to extra forms, those that aren’t attached to an existing model instance. …