Reputation: 151
I am trying to use an inlineformset to create a parent model and some children models. Below is my view. The code works in saving the initial Rfq model to the database, but errors when it tries to save the lines inlineformset. This is a one-to-many relationship, but is done using the ForeignKey field.
# views.py
def rfq_create(request):
form = RfqForm(request.POST or None)
RfqFormSet = inlineformset_factory(Rfq, Rfqlines, form=RfqlinesForm, extra=5, can_delete=True)
lines_formset = RfqFormSet(request.POST or None)
title = "Create a new RFQ"
context = {
"title": title,
"form": form,
"lines_formset": lines_formset,
}
if form.is_valid() and lines_formset.is_valid():
rfq = form.save(commit=False)
rfq.user = request.user
rfq.save()
lines_formset.save()
rfq_list = Rfq.objects.order_by('rfq_id')[:20]
title = "RFQ List"
context = {
"title": title,
"rfq_list": rfq_list
}
return render(request, "rfq.html", context)
return render(request, "rfq_create.html", context)
I've tried looking at the official Django docs, but it doesn't seem to apply ... or isn't that straightforward anyways.
Here is my traceback
Environment:
Request Method: POST
Request URL: http://localhost:8000/rfq/create
Django Version: 1.8.7
Python Version: 3.4.3
Installed Applications:
('django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.humanize',
'django.forms.formsets',
'jquery',
'crispy_forms',
'registration',
'home',
'rfq',
'dashboard',
'pipeline')
Installed Middleware:
('django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware')
Traceback:
File "/home/brandon/employees/env/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
132. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/brandon/employees/rfq/views.py" in rfq_create
36. lines_formset.save()
File "/home/brandon/employees/env/lib/python3.4/site-packages/django/forms/models.py" in save
636. return self.save_existing_objects(commit) + self.save_new_objects(commit)
File "/home/brandon/employees/env/lib/python3.4/site-packages/django/forms/models.py" in save_new_objects
767. self.new_objects.append(self.save_new(form, commit=commit))
File "/home/brandon/employees/env/lib/python3.4/site-packages/django/forms/models.py" in save_new
900. obj.save()
File "/home/brandon/employees/env/lib/python3.4/site-packages/django/db/models/base.py" in save
685. "unsaved related object '%s'." % field.name
Exception Type: ValueError at /rfq/create
Exception Value: save() prohibited to prevent data loss due to unsaved related object 'rfq'.
Upvotes: 4
Views: 5459
Reputation: 151
The answer to the problem was this
lines_formset = RfqFormSet(request.POST or None, instance=form.instance)
the form.instance was the key that was overlooked.
Upvotes: 11
Reputation: 3752
You need to pass your parent model instance to the inline_formset.
See this relevant section of the Django docs, for more info.
Example:
lines_formset = RfqFormSet(request.POST, request.FILES, instance=rfq)
This is necessary so Django can appropriately set the ForeignKey relationships of the child models.
Upvotes: 4