Opened 11 years ago
Last modified 11 years ago
#24541 closed Cleanup/optimization
save_new_objects in ModelFromsets do not handle intitial data — at Version 5
| Reported by: | Johannes Maron | Owned by: | nobody |
|---|---|---|---|
| Component: | Documentation | Version: | dev |
| Severity: | Normal | Keywords: | modelformset |
| 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 (last modified by )
If you create a ModelFormSet and pass initial data for some forms, the forms are evaluated as has_changed False.
All in all that is true, but it has the the side effect that the forms in the formset don't get saved, tho they contain data.
The error is here:
https://github.com/django/django/blob/master/django/forms/models.py#L777-L778
It should not only be checked for has_changed but also for initial data.
Change History (5)
comment:1 by , 11 years ago
| Resolution: | → invalid |
|---|---|
| Status: | new → closed |
comment:2 by , 11 years ago
| Resolution: | invalid |
|---|---|
| Status: | closed → new |
That does not work for ModelFormSets as the pop initial to initial_extra and only except existing objects using the Queryset.
There currently is no way to create objects using a ModelFormSet with initial data.
I get your point, about compatibility, but you should decide if this odd behavior is a bug or a feature. Personally it feels like a bug. Especially as Model and regular form sets handle initial data so differently. There is no consistent behavior nor any documentation about this.
comment:3 by , 11 years ago
| Easy pickings: | unset |
|---|
I had no trouble with this view:
from django.forms.models import modelformset_factory
def test_view(request):
qs = Poll.objects.none()
PollFormSet = modelformset_factory(Poll, fields='__all__')
if request.method == 'POST':
formset = PollFormSet(request.POST, queryset=qs)
if formset.is_valid():
formset.save()
else:
formset = PollFormSet(queryset=qs, initial=[
{'question': 'initial', 'pub_date': timezone.now()}])
return render(request, 'polls/manage.html', {'formset': formset})
Can you provide a snippet that demonstrates your problem?
comment:4 by , 11 years ago
As I said:
It does not work if your submitted are not yet created and you can't pass a queryset.
from django.forms.models import modelformset_factory
def test_view(request):
qs = Poll.objects.none()
PollFormSet = modelformset_factory(Poll, fields='__all__')
if request.method == 'POST':
formset = PollFormSet(request.POST, initial=[{'question': 'Foo'}, {'question': 'Bar'}])
if formset.is_valid():
obj_list = formset.save()
assert len(obj_list) == 2
else:
formset = PollFormSet(queryset=qs, initial=[
{'question': 'initial', 'pub_date': timezone.now()}])
return render(request, 'polls/manage.html', {'formset': formset})
This will fail.
comment:5 by , 11 years ago
| Description: | modified (diff) |
|---|
You should use initial forms instead of extra forms if you require those populated forms to be submitted. Changing the behavior to validate and save unchanged extra forms would be backwards incompatible. Feel free to reopen if I missed something.