'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 |
|---|
