Opened 6 years ago
Last modified 6 years ago
#29739 closed Bug
BaseModelFormSet ignores excess rows in initial when extra < len(initial) — at Version 2
Reported by: | Mark Gensler | Owned by: | nobody |
---|---|---|---|
Component: | Forms | Version: | 2.1 |
Severity: | Normal | Keywords: | modelformset |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
When passing initial data through BaseModelFormSet.__init__(..., initial=)
and the length of the initial data exceeds the number of extra forms defined in modelformsetfactory(..., extra=)
, then the data in the range self.initial_extra[self.extra:]
will be ignored.
E.g.
class Person(models.Model): name = models.CharField(max_length=100) initial = [{'name': 'Foo'}, {'name': 'Bar'}, {'name': 'Baz'}] PersonFormSet = modelformsetfactory(Person, extra=2) formset = MyModelFormSet(initial=initial)
Now, assuming that models.Person.objects.all()
is empty,
len(formset.forms) == 2 True
This is because BaseFormSet.total_form_count()
blindly uses self.extra and does not take into account the additional data in self.initial_extra
.
In order to work around this users would check len(initial)
before constructing the class and modify the extra
kwarg to be large enough. This causes issues when writing abstract code which constructs the class separately from initialising it, or reuses the same class with differing initial data. In these cases the length of the initial data may not be known at the time of class construction.
Possible solutions are the number of extra forms equals self.extra + len(self.initial_extra)
or max(self.extra, len(self.initial_extra))
.
I am happy to write a patch for this. I lean towards
max
rather than addinglen(initial_extra)
forms, it all depends on the philosophy of whatextra
represents.A fix could be implemented by either adding a
BaseModelFormSet.total_form_count()
method, or adding aBaseFormSet.get_extra_form_count()
method analogous toget_initial_form_count()
and overwritten byBaseModelFormSet
. I am happy to do either if someone could provide a preference.