Question:
Ways to access instances of models in view in order to save both forms at once in Django

Problem

I am trying to combine two models into one form. However I cannot save the form as it is not an instance of the models. What I'm after is a way to access the models as instances and then save them. I am using crispy forms, I have described what I have tried at the bottom of the post, I have no idea why this is not working so as always any help is appreciated.


This is my model.py file:


from Django.db import models


# Create your models here.


BOOKING_STATUS = ((0, 'To be confirmed'), (1, 'Confirmed'), (2, 'Declined'))



class Customer(models.Model):

    first_name = models.CharField(max_length=80)

    last_name = models.CharField(max_length=80)

    email = models.EmailField()

    phone_number = models.CharField(max_length=20)


    def __str__(self):

        return f"Customer {self.first_name + ' ' + self.last_name}"



class Booking(models.Model):

    booking_date = models.DateField()

    booking_time = models.TimeField()

    number_attending = models.IntegerField(default=2)

    booking_status = models.IntegerField(choices=BOOKING_STATUS, default=0)

    customer = models.ForeignKey('Customer', on_delete=models.CASCADE)


    def __str__(self):

        return f"Booking by {self.customer}"


forms.py:


from .models import Customer, Booking

from django import forms



class CustomerForm(forms.ModelForm):

    class Meta:

        model = Customer

        fields = '__all__'



class BookingForm(forms.ModelForm):

    class Meta:

        model = Booking

        fields = ('booking_date', 'booking_time', 'number_attending')



class CustomerBookingForm(forms.Form):

    customer_form = CustomerForm()

    booking_form = BookingForm()


and my view.py


from django.shortcuts import render

from .forms import CustomerBookingForm



# Create your views here.


# https://stackoverflow.com/questions/51459435/django-create-multiple-instance-of-model-with-one-form

def customer_booking(request):

    if request.method == 'POST':

        customer_booking_form = CustomerBookingForm(request.POST)

        # if customer_booking_form.is_valid():


    else:

        customer_booking_form = CustomerBookingForm()


    context = {

        'form': customer_booking_form,

    }


    return render(request, 'booking.html', context)


I have tried:

  booking_instance = customer_booking_form.cleaned_data['booking_form'].save()


However, this is not recognizing the fields 'customer_form' or 'booking_form'



Solution

Instantiate both forms in your view, just add a prefix argument to at least one of them.


def customer_booking(request):

    if request.method == "POST":

        customer_form = CustomerForm(request.POST, prefix="customer")

        booking_form = BookingForm(request.POST, prefix="booking") 

        # if customer_form.is_valid()

        # if booking_form.is_valid()

        ..... 

    else:

        customer_form = CustomerForm(prefix="customer")

        booking_form = BookingForm(prefix="booking") 



The prefix will let Django give each form a unique namespace. So, the field name values will have the specified prefix for that ModelForm, i.e., customer-first_name, booking-booking_time, etc.


Answered by: >McPherson

Credit: >StackOverflow


Blog links:

>How to show encrypted user id in URL in Laravel?

>How to fix Laravel LiveWire listener?

>Run Laravel Project to Active Local Server


Nisha Patel

Nisha Patel

Submit
0 Answers