#29160 closed Bug (invalid)
Django ModelForm doesn't parse foreign keys in initial= kwarg.
Reported by: | Hameer Abbasi | Owned by: | nobody |
---|---|---|---|
Component: | Forms | Version: | 1.11 |
Severity: | Normal | Keywords: | initial |
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 )
Django forms don't parse foreign keys in the initial=
kwarg. It gives a "NOT NULL constraint failed" even if the said data has been specified. This is inconvenient for forms since an instance
can be specified but critical for formsets where it can't.
Relevant files:
models.py
Code highlighting:
from django.db import models class BaseModel(models.Model): pass # Create your models here. class SimpleModel(models.Model): field = models.IntegerField(default=0) hidden_fk = models.ForeignKey(BaseModel, null=False)
forms.py
Code highlighting:
from django import forms from . import models class SimpleForm(forms.ModelForm): class Meta: model = models.SimpleModel fields = ['field'] SimpleFormset = forms.modelformset_factory(models.SimpleModel, fields=['field'], extra=3)
views.py
Code highlighting:
from django import views from django.template import loader from django.http import HttpResponse from . import forms from . import models # Create your views here. class FormView(views.View): template = 'thing/form.html' def get(self, request): context = {'form': forms.SimpleForm()} template = loader.get_template(self.template) return HttpResponse(template.render(context, request)) def post(self, request): base_model = models.BaseModel.objects.get(id=1) form = forms.SimpleForm(request.POST, initial={'hidden_fk': base_model}) context = {'form': form} template = loader.get_template(self.template) simple_model = form.save(commit=False) simple_model.field = 1 form.save() return HttpResponse(template.render(context, request)) class FormSetView(views.View): template = 'thing/formset.html' def get(self, request): context = {'formset': forms.SimpleFormset()} template = loader.get_template(self.template) return HttpResponse(template.render(context, request)) def post(self, request): base_model = models.BaseModel.objects.get(id=1) formset = forms.SimpleFormset( request.POST, initial=[{'hidden_fk': base_model}] * forms.SimpleFormset.extra ) context = {'formset': formset} template = loader.get_template(self.template) if formset.is_valid(): formset.save() return HttpResponse(template.render(context, request))
Attachments (1)
Change History (5)
by , 7 years ago
Attachment: | sample_project.zip added |
---|
comment:1 by , 7 years ago
Type: | Uncategorized → Bug |
---|
comment:2 by , 7 years ago
Description: | modified (diff) |
---|
comment:3 by , 7 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
This looks like a misunderstanding of how Form.initial
works. From the documentation:
[
Form.initial
] values are only displayed for unbound forms, and they’re not used as fallback values if a particular value isn’t provided.
I only looked at this briefly, so if I've misunderstood the issue please reopen and point to the incorrect code in Django.
comment:4 by , 7 years ago
I won't reopen since you're probably right, but then there is no way to pass an instances=
to a ModelFormSet
. Because of this, when certain FKs are missing, you can't validate them later because the ModelFormSet
fails to validate even with commit=False
. This is probably a separate issue though. See https://stackoverflow.com/questions/48961675/modify-data-in-formset-before-validation for details on what I want to do, except I want to inject an FK.
Sample project demonstrating the issue.