Brandon C. Brown
Brandon C. Brown

Reputation: 151

django save() prohibited to prevent data loss due to unsaved related object

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

Answers (2)

Brandon C. Brown
Brandon C. Brown

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

Nostalg.io
Nostalg.io

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

Related Questions