why form.is_valid() is always false?

Question:

I tried to create a contact us form in django but i got always false when i want to use .is_valid() function.

this is my form:

from django import forms
from django.core import validators


class ContactForm(forms.Form):
    first_name = forms.CharField(
        widget=forms.TextInput(
            attrs={'placeholder': 'نام خود را وارد کنید'}),
        label="نام ",
        validators=[
            validators.MaxLengthValidator(100, "نام شما نمیتواند بیش از 100 کاراکتر باشد")])

    last_name = forms.CharField(
        widget=forms.TextInput(
            attrs={'placeholder': 'نام خانوادگی خود را وارد کنید'}),
        label="نام خانوادگی",
        validators=[
            validators.MaxLengthValidator(100, "نام خانوادگی شما نمیتواند بیش از 100 کاراکتر باشد")])

    email = forms.EmailField(
        widget=forms.EmailInput(
            attrs={'placeholder': 'ایمیل خود را وارد کنید'}),
        label="ایمیل",
        validators=[
            validators.MaxLengthValidator(200, "تعداد کاراکترهایایمیل شما نمیتواند بیش از ۲۰۰ کاراکتر باشد.")
        ])

    title = forms.CharField(
        widget=forms.TextInput(
            attrs={'placeholder': 'عنوان پیام خود را وارد کنید'}),
        label="عنوان",
        validators=[
            validators.MaxLengthValidator(250, "تعداد کاراکترهای  شما نمیتواند بیش از 250 کاراکتر باشد.")
        ])

    text = forms.CharField(
        widget=forms.Textarea(
            attrs={'placeholder': 'متن پیام خود را وارد کنید'}),
        label="متن پیام",
    )

    def __init__(self, *args, **kwargs):
        super(ContactForm, self).__init__()
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'form_field require'

this is my view:

from django.shortcuts import render

from .forms import ContactForm
from .models import ContactUs


def contact_us(request):
    contact_form = ContactForm(request.POST or None)
    if contact_form.is_valid():
        first_name = contact_form.cleaned_data.get('first_name')
        last_name = contact_form.cleaned_data.get('last_name')
        email = contact_form.cleaned_data.get('email')
        title = contact_form.cleaned_data.get('title')
        text = contact_form.cleaned_data.get('text')

        ContactUs.objects.create(first_name=first_name, last_name=last_name, email=email, title=title, text=text)
        # todo: show user success message

        contact_form = ContactForm()
    context = {
        'form': contact_form
    }

    return render(request, 'contact_us/contact_us.html', context)

** this is the codes in template**

  <form action="{% url 'contact' %}" id="contactform" method="post">
                                {% csrf_token %}
                                <div class="col-md-6 col-lg-6">
                                    <div class="form_block">
                                        {{ form.first_name }}
                                        {% for error in form.first_name.errors %}
                                            <p class="text-danger">{{ error }}</p>
                                        {% endfor %}
                                    </div>
                                </div>
                                <div class="col-md-6 col-lg-6">
                                    <div class="form_block">
                                        {{ form.last_name }}
                                        {% for error in form.last_name.errors %}
                                            <p class="text-danger">{{ error }}</p>
                                        {% endfor %}
                                    </div>
                                </div>
                                <div class="col-md-6 col-lg-6">
                                    <div class="form_block">
                                        {{ form.email }}
                                        {% for error in form.email.errors %}
                                            <p class="text-danger">{{ error }}</p>
                                        {% endfor %}
                                    </div>
                                </div>
                                <div class="col-md-6 col-lg-6">
                                    <div class="form_block">
                                        {{ form.title }}
                                        {% for error in form.title.errors %}
                                            <p class="text-danger">{{ error }}</p>
                                        {% endfor %}
                                    </div>
                                </div>
                                <div class="col-md-12 col-lg-12">
                                    <div class="form_block">
                                        {{ form.text }}
                                        {% for error in form.text.errors %}
                                            <p class="text-danger">{{ error }}</p>
                                        {% endfor %}

                                        <div class="response"></div>
                                    </div>
                                </div>
                                <div class="col-md-12 col-lg-12">
                                    <div class="form_block">
                                        <button type="submit" class="clv_btn submitForm"
                                                data-type="contact">ارسال
                                        </button>
                                    </div>
                                </div>
                            </form>
Asked By: Pøyã Shadman

||

Answers:

you can use CBVs to easily save data on form valid

views.py

from django.views import generic

class ContactCreateView(generic.CreateView,):
    model = Contact
    fields = "__all__"   
    success_url = reverse_lazy(url_name)

then in in your templates

templates/contact_form.html


<form action="{% url 'contact' %}" id="contactform" method="post">
    {% csrf_token %}
  {% for formfield in form %}
   <div class="col-md-6 col-lg-6">
       <div class="form_block">
           {{ formfield}}
           {% for error in formfield.errors %}
               <p class="text-danger">{{ error }}</p>
           {% endfor %}
       </div>
     </div>
#add submit button here

urls.py
just remember to add as_view() when calling your view in url

    path("", views.ContactCreateView.as_view(), name="contact"),

or using FBV you could try:

def contact_us(request):
    contact_form = ContactForm(request.POST or None)
    if contact_form.is_valid():
        contact_form.save()
       
        
    context = {
        'form': contact_form
    }

    return render(request, 'contact_us/contact_us.html', context)


Answered By: Dante

Alter the super() constructor in init override at forms.py:

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        for visible in self.visible_fields():
            visible.field.widget.attrs['class'] = 'form_field require'

Fix your view based on documentation:

def contact_us(request):
    if request.method == 'POST':
        contact_form = ContactForm(request.POST)
        if contact_form.is_valid():
            ContactUs.objects.create(**contact_form.cleaned_data)
            messages.success(request, 'My success message')
            # you want to send to your home
            return redirect('/contact')

    else:
        contact_form = ContactForm()
    context = {
        'form': contact_form
    }

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

I took the liberty to clean up your view by using **kwargs since you have many fields. Used Django messages to display successful message on obj creation. Here is how to display it.

Answered By: Niko
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.