Home > Software engineering >  How to save multiple objects at once to Django database
How to save multiple objects at once to Django database

Time:04-21

I'm trying to get form data using a POST request and save the form data to my database which was created using a django model named InfoModel. I'm getting the data from the POST request, but I don't know how to save all of it at once so that it all saves to the same row in the db. The way I'm doing it now, each object from the form saves to a different row of the database which is obviously not useful at all. I expect the answer is simple, but I haven't seen this in the docs.

views.py

from django.shortcuts import render

from django.http import HttpResponseRedirect

from .forms import InfoForm

from .models import InfoModel

# Create your views here.

def home(request):

if request.method == 'POST':
    #if POST request, validate the data 

    form = InfoForm(request.POST)

    if form.is_valid():
        #if the form is valid, collect the data, submit to db, and thank the user
        
        valid = True
        
        form_data = request.POST
        
        f = InfoModel(fname = form_data['fname'])
        
        f.save()
        
        l = InfoModel(lname = form_data['lname'])
        
        l.save()
        
        e = InfoModel(email = form_data['email'])
        
        e.save()
        
        p = InfoModel(phone = form_data['phone'])
        
        p.save()
         
        return render(request, 'form_db/home.html', {'form':form, 'valid':valid})
    
    else:
        #if the form is invalid, populate the form with the entered data and show error message
        valid = False
        
        form = InfoForm(request.POST)
        
        return render(request, 'form_db/home.html', {'form':form, 'valid':valid})

else:
    #if GET request, return blank form as normal 

    form = InfoForm()
 
    return render(request, 'form_db/home.html', {'form':form})

'''

CodePudding user response:

You can simply, give all fields' names of your InfoModel at once in the following way:

if form.is_valid():
    valid=True
    fName=form.cleaned_data['fname']
    lname=form.cleaned_data['lname']
    email=form.cleaned_data['email']
    phone=form.cleaned_data['phone']
 
    instance=InfoModel(fname=fName,lname=lname,email=email,phone=phone)
    instance.save()
    return render(request,"form_db/home.html",{'form': form,'valid':valid})
    

Note: Models in django doesn't require model to be the suffix, so it will be better if you only give model name Info rather than InfoModel.

CodePudding user response:

Every time you call f = InfoModel() you are instantiating a new instance, and then saving it using f.save(), which is why you are getting so many rows. All this is unnecessary since a form has it's own save() method, which will save all the fields at once into ONE row.

The best way to handle forms is to use the classic Post/Redirect/Get method where if the form data comes in as Post, then you process it and redirect, usually back to the same view, but it can be another view as well. If it is a Get, then you render the blank form.

def home(request):

    if request.method == 'POST':
        
        form = InfoForm(request.POST or None)
        
        if form.is_valid():
            form.save()
            return redirect('home')
     
        return render(request, 'form_db/home.html', {'form':form})

Note the form = InfoForm(request.POST or None), which is handy since it will create a blank form with the None if it is not a Post request, but if it is will fill the form with the data request.POST if it's a Post request.

  • Related