#16995 closed Bug (fixed)
ModelFormSet initial data from initial parameter uses "extra" forms
Reported by: | Owned by: | Mark Gensler | |
---|---|---|---|
Component: | Documentation | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Ready for checkin | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
It seems that when you feed initial data into a ModelFromSet using the initial parameter, it uses the "extra" forms that you define with the extra parameter in the modelformset_factory. For example, if you feed a list of two dictionaries (with the model data) into the initial parameter of a FormSet, but the formset_factory that the FormSet was created from has an extra parameter of 1 (or None), then only the model data from the first dictionary in the list will show up in the FormSet.
Since "initial" data doen't seem like they should be in the "extra" forms, I think this is a bug?
Change History (8)
comment:1 by , 13 years ago
Component: | Forms → Documentation |
---|---|
Triage Stage: | Unreviewed → Accepted |
Version: | 1.3 → SVN |
comment:2 by , 13 years ago
I was about to report this as a separate bug (after asking in #django-dev
); I see this is as a feature proposal along the lines of "Set extra
to the length of initial
in ModelFormSet if it is not set manually".
I'm using modelformset_factory
to create a model formset class, then passing initial
in the constructor when instantiating it. Line 91 of forms/formsets.py
uses the value of extra
to work out how many extra
forms should be drawn, but I think this information could already be implied by the length of the initial
dict, at least in the case where extra
is not specified (for backwards compatibility), and having to specify both seems a little like Repeating Yourself.
The code I'm using which demonstrates the problem is here.
I can certainly try writing a patch (it shouldn't be a big change, and I imagine the tests would be pretty straightforward) if this seems like a good idea. If not, I agree that the "Making forms from models" docs should explain that extra
needs to be set, even with initial
, using something like
from django.forms.models import modelformset_factory foos = some_function_that_returns_a_list_of_foo() FooFormSet = modelformset_factory(Foo, extra=len(foos)) foo_formset = FooFormSet(initial=[f.__dict__ for f in foos])
comment:3 by , 11 years ago
The quick workaround on this is to use lambda function:
from django.forms.models import modelformset_factory foos = some_function_that_returns_a_list_of_foo() FooFormSet = lambda *args, **kwargs: modelformset_factory(Foo, extra=kwargs.pop('extra', 0))(*args, **kwargs) foo_formset = FooFormSet(initial=[f.__dict__ for f in foos], extra=len(foos))
comment:4 by , 6 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
I will work on adding this to the documentation.
comment:5 by , 6 years ago
Has patch: | set |
---|
Patch and pull request created at https://github.com/django/django/pull/10372
comment:6 by , 6 years ago
Triage Stage: | Accepted → Ready for checkin |
---|
I believe this is working as designed. I do, however, think the documentation is lacking in clarity and there's an inconsistency with how
initial
works in a regularFormSet
.With a
FormSet
,extra
forms are those beyond the ones created by the data ininitial
, as documented here.With a
ModelFormSet
, the data in the non-extra forms is determined by the existing model instances. It's sometimes useful to be able to pre-populate some of the extra forms with some initial data, and that's what theinitial
parameter is used for. Ifinitial
pre-populated the non-extra forms, how would the conflict with existing model instance data be resolved?If this were being designed from scratch, you could perhaps make a case that a
ModelFormSet
should consist of first the forms representing existing instances, then forms representing the giveninitial
data, then emptyextra
forms (i.e.initial
would add more forms, not prepopulate theextra
forms). This would perhaps be more consistent withFormSet
, but I'm not sure it's actually better for real usage.In any case, if it's an improvement at all, it's not enough of one to justify making a backwards-incompatible change. So I'm converting this into a documentation bug; the
ModelFormSet
docs should have an explanation of howinitial
andextra
interact differently in aModelFormSet
than in aFormSet
.