I have a problem with a django formset that I can't really explain to myself. Here is the involved code.
forms.py:
class ScoreForm(forms.ModelForm):
class Meta:
model = models.Score
fields = (
'period',
'home_team_score',
'away_team_score',
)
ScoreFormSet = forms.inlineformset_factory(
models.Fixture,
models.Score,
form=ScoreForm,
extra=5
)
models.py:
class Score(models.Model):
fixture = models.ForeignKey(Fixture, related_name="score")
user = models.ForeignKey(settings.AUTH_USER_MODEL, related_name="score")
inserted_at = models.DateTimeField(auto_now_add=True, blank=True, null=True)
period = models.IntegerField(blank=True, null=True)
home_team_score = models.IntegerField(blank=True, null=True)
away_team_score = models.IntegerField(blank=True, null=True)
class Meta:
db_table = 'score'
views.py:
class InsertScoreView(CreateView):
form_class = forms.ScoreForm
model = Score
template_name = 'gamestream/insert_score.html'
success_url = "/gamestream/score_list/"
def get_context_data(self, **kwargs):
fixture = Fixture.objects.get(id=self.kwargs['fixture_id'])
data = super(InsertScoreView, self).get_context_data(**kwargs)
if self.request.POST:
data['scores'] = forms.ScoreFormSet(self.request.POST)
data['fixture'] = fixture
else:
data['scores'] = forms.ScoreFormSet()
data['fixture'] = fixture
return data
def form_valid(self, form, **kwargs):
user = self.request.user
fixture = Fixture.objects.get(id=self.kwargs['fixture_id'])
context = self.get_context_data()
formset = forms.ScoreFormSet(self.request.POST)
if formset.is_valid():
scores = formset.save(commit=False)
for score in scores:
score.fixture = fixture
score.user = user
score.save()
return super(InsertScoreView, self).form_valid(form)
and the template:
<div class="container">
<h3>Please insert scores for the following match:</h3>
<h4>{{ fixture.starting_time }} -- {{ fixture.league.league_name }} -- {{ fixture.home_team }} vs {{ fixture.away_team }}</h4>
<form action="." method="POST">
{% csrf_token %}
{{ scores.management_form }}
{% for form in scores %}
<p>{{ form }}</p>
{% endfor %}
<input type="submit" value="Insert score" class="submit" />
</form>
</div>
I get this behavior: I am able to insert ALL the values that I want. It does not matter if 1 or 5 they get inserted and saved to the db (which is correct, that's what I want to achieve). The problem is that it looks like and extra 100% blank form gets sent through and that does not validate (because the fixture field is required)! I have removed the constraints in the fixture field of the Score model (for testing purposes) and in fact a completely blank line get inserted into the db. This is why I believe a blank form is being sent through.
I can't really explain this behavior. Where does that blank form (or whatever it is) come from? 🤔
Thanks, Vittorio
So after a lot of tries I have changed the type of the view: from CreateView to FormView and it suddenly started to work just fine.
I can't really provide more info on this as I do not really know what the difference in the code between the 2 classes is.