'Django Model Form is Failing Validation with Defaults Set in Model

Background: I am trying to implement a new user registration flow that adds in a verification step (using OTP) for their phone number and email address. Multiple forms are being submitted via JS and the edited in the views.py def registration().

Goal: Validate all of the forms and then save them

Issue: My Customer forms will not validate. I am getting the following errors: {'status': [ValidationError(['This field is required.'])], 'customer_number': [ValidationError(['This field is required.'])], 'payment_term': [ValidationError(['This field is required.'])], 'discount': [ValidationError(['This field is required.'])]}

What I have tried: I have tried to use both a Model form and a non-model form to no avail. When I use a non-model form I get a "Object has no save function" and when I use the Model form then I get the above stated error. I am not sure why I cannot submit this form with the fields being blank as they all have a default set.

models.py

class Customer(BaseModel):

    status = models.CharField("Status", max_length=2, choices=STATUS_OPTIONS, default="A")
    customer_name = models.TextField("Customer Name", max_length=100, unique=True)
    customer_number = models.TextField(max_length=19, unique=True, default=get_customer_number)
    phone_number = models.CharField(max_length=16, unique=True)
    payment_term = models.CharField("Payment Terms", max_length=4, choices=PAYMENT_TERM_OPTIONS, default="100P")
    discount = models.DecimalField("Discount", max_digits=2, decimal_places=2, default="0")

views.py

def register(request):


    if request.user.is_authenticated:
        return HttpResponseRedirect('/portal')

    if request.method == 'POST':
        code = random.randint(10000,99999) if not getattr(settings, 'DEBUG') else 1234

        print(dict(request.POST.items()))
        user_form = UserRegisterForm(request.POST)
        profile_form = ProfileUpdateForm(request.POST)
        customer_form = CustomerCreateForm(request.POST)
        customer_m_form = CustomerCreateModelForm(request.POST)
        address_form = AddressCreateModelForm(request.POST)


        if user_form.is_valid():
            user = user_form.save(commit=False)
            user.status = "D"

            # login(request, user)

            if customer_form.is_valid():

                customer = customer_m_form
                customer.status = "D"
                customer.customer_number = ""
                customer.payment_term = ""
                customer.discount = ""
                profile_form.user = user
                profile_form.customer = customer

                if customer.is_valid():
                    print("customer model form is valid")
                    customer_m_form.save(commit=False)
                    address = address_form
                    address.customer = customer
                else:
                    print(customer_m_form.errors.as_data())

                if address_form.is_valid():
                    print("address form is valid")
                    address_form.save(commit=False)

                    if profile_form.is_valid():
                        print("profile form is valid")
                        user.save()
                        customer.save()
                        address.save()
                        profile_form.save()

                        messages.success(request,
                                         f'We have sent you a verification code, please verify your email and phone number!')
                        request.session['user'] = user.id

                        GeneralOTP.objects.filter(user=user).update(is_active=False)
                        otp = GeneralOTP.objects.create(
                            user=user,
                            code=code
                        )

                        send_mail(
                            'Your verification code',
                            'Here is the code '.format(otp.code),
                            settings.FROM_EMAIL,
                            [str(otp.user.email), ],
                            fail_silently=False,
                        )
                        if getattr(settings, 'TWILIO_SID', ''):
                            send_sms(otp.phone_number, otp.code)

                        return redirect('profile')
                    # return redirect('general_otp')
        messages.error(request, 'Sorry, it appears there were some issues that need to be addressed before the account can be created. Please see the highlighted fields that need to be corrected.')

        context = {
            'customer_form': customer_form,
            'user_form': user_form,
            'profile_form': profile_form,
        }


        return render(request, 'users/register.html', context)
    else:

        customer_form = CustomerCreateForm()
        user_form = UserRegisterForm()
        profile_form = ProfileUpdateForm()

    context = {
        'customer_form': customer_form,
        'user_form': user_form,
        'profile_form': profile_form,
    }

    return render(request, 'users/register.html', context)

forms.py

class CustomerCreateForm(forms.Form):

    customer_name = forms.CharField(widget=forms.TextInput(attrs={'placeholder':"Customer Name"}))
    phone_number = forms.CharField(widget=forms.TextInput(attrs={'placeholder':"Company Phone Number"}))
    address_type = forms.ChoiceField(choices=ADDRESS_TYPE_OPTIONS)
    street_address_1 = forms.CharField(widget=forms.TextInput(attrs={'placeholder':"Street Address"}))
    street_address_2 = forms.CharField(widget=forms.TextInput(attrs={'placeholder':"Street Address 2 (optional)"}))
    city = forms.CharField(widget=forms.TextInput(attrs={'placeholder':"City"}))
    region = forms.ChoiceField(choices=REGIONS_OPTIONS)
    postal_code = forms.CharField(widget=forms.TextInput(attrs={'placeholder':"Postal Code"}))
    country = forms.ChoiceField(choices=COUNTRY_OPTIONS)
    account_type = forms.ChoiceField(choices=[('',"Select Option"), ('New Company','Yes, our Company is new to ICS and want to set up a brand new account'), ('New User','No, our Company has an account but our team is growing and we need to add a new user to our existing account'), ('Login', "No, I'm lost and just want to login")])

    def __init__(self, *args, **kwargs):
        super(CustomerCreateForm, self).__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.fields['street_address_2'].required = False
        self.helper.form_show_labels = False
        self.helper.form_method = 'POST'
        self.helper.attrs = {
            'novalidate': ''
        }

class CustomerCreateModelForm(forms.ModelForm):

    class Meta:
        model = Customer
        exclude = ['history',]


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source