VIVEK YADAV
VIVEK YADAV

Reputation: 23

Django Form Validation Error?

I'm trying to run and validate a form but having some problem. Instead of displaying the form it renders the template which I put to display when the form is not valid.

Here is my Model:

class Preference(models.Model):
    CLASS_CHOICES = [('1', '1'), ('2', '2'), ('3', '3')]
    BOARD_CHOICES = [('C', 'CBSE'), ('I', 'ICSE'), ('S', 'State Board')]
    SLOT_CHOICES = [('M', 'Morning'), ('A', 'AfterNoon'), ('E', 'Evening')]
    SUBJECT_CHOICES = [('H', 'HINDI'), ('M', 'MATH'), ('E', 'ENGLISH')]
    LOCATION_CHOICES = [('M', 'My Home'), ('T', 'I am willing to travel')]
    GENDER_CHOICES = [('M', 'Male'), ('F', 'Female'), ('B', 'Both are Fine')]
    Class = models.CharField(max_length=2, choices=CLASS_CHOICES, default='1', blank=False)
    Board = models.CharField(max_length=2, choices=BOARD_CHOICES, default='C', blank=False)
    Subject = models.CharField(max_length=2, choices=SUBJECT_CHOICES, default='M', blank=False)
    Frequency = models.IntegerField(default=7)
    Slot = models.CharField(max_length=2, choices=SLOT_CHOICES, default='E', blank=False)
    Location = models.CharField(max_length=2, choices=LOCATION_CHOICES, default='M', blank=False)
    Gender = models.CharField(max_length=2, choices=GENDER_CHOICES, default='M', blank=False)
    Address = models.CharField(max_length=250, blank=True)
    Travel = models.IntegerField(default=5)
    Name = models.CharField(max_length=50, blank=True)
    Contact = models.IntegerField(default=100)

Here is my form:

class PreferenceForm(forms.ModelForm):
    class Meta:
        model = Preference
        fields = ['Class', 'Board', 'Subject', 'Frequency', 'Slot', 'Location', 'Gender', 'Address',
                  'Travel', 'Name', 'Contact']
        widgets = {
               'Board': forms.RadioSelect(),
               'Subject': forms.CheckboxSelectMultiple(),
               'Slot': forms.CheckboxSelectMultiple(),
               'Location': forms.CheckboxSelectMultiple(),
               'Gender': forms.RadioSelect()}

And here is my view:

def pref2(request):
    form = PreferenceForm(request.POST or None)
    if form.is_valid():
        prefer = form.save(commit=False)
        prefer.save()
        return HttpResponse('Thank You!')
    else:
        print(form.errors)
        return render(request, 'website/tutors.html')

When I run the app, it renders the 'tutors.html' template without showing the form and form.errors display no error.

All help/suggestions are appreciated, thanks.

Upvotes: 0

Views: 230

Answers (1)

nik_m
nik_m

Reputation: 12086

[EDIT]: The validation error you get is explained very well here. In order to make it work, you should add 3 more models:

class Subject(models.Model):
    SUBJECT_CHOICES = [('H', 'HINDI'), ('M', 'MATH'), ('E', 'ENGLISH')]

    name = models.CharField(max_length=2, choices=SUBJECT_CHOICES, default='M', blank=False)

    def __str__(self):
        return self.name


class Slot(models.Model):
    SLOT_CHOICES = [('M', 'Morning'), ('A', 'AfterNoon'), ('E', 'Evening')]

    name = models.CharField(max_length=2, choices=SLOT_CHOICES, default='E', blank=False)

    def __str__(self):
        return self.name

class Location(models.Model):
    LOCATION_CHOICES = [('M', 'My Home'), ('T', 'I am willing to travel')]

    name = models.CharField(max_length=2, choices=LOCATION_CHOICES, default='M', blank=False)

    def __str__(self):
        return self.name

Now, in your Preference model, change it to:

class Preference(models.Model):
    CLASS_CHOICES = [('1', '1'), ('2', '2'), ('3', '3')]
    BOARD_CHOICES = [('C', 'CBSE'), ('I', 'ICSE'), ('S', 'State Board')]
    GENDER_CHOICES = [('M', 'Male'), ('F', 'Female'), ('B', 'Both are Fine')]

    Class = models.CharField(max_length=2, choices=CLASS_CHOICES, default='1', blank=False)
    Board = models.CharField(max_length=2, choices=BOARD_CHOICES, default='C', blank=False)
    subjects = models.ManyToManyField(Subject)
    Frequency = models.IntegerField(default=7)
    slots = models.ManyToManyField(Slot)
    locations = models.ManyToManyField(Location)
    Gender = models.CharField(max_length=2, choices=GENDER_CHOICES, default='M', blank=False)
    Address = models.CharField(max_length=250, blank=True)
    Travel = models.IntegerField(default=5)
    Name = models.CharField(max_length=50, blank=True)
    Contact = models.IntegerField(default=100)

Also, please, rename your fields to lower case (address instead of Address). First-letter-uppercase is used for Class names. After that, run ./manage.py makemigrations and ./manage.py migrate to apply the changes.

[END EDIT]

It seems that you do not display your form in your tutors.html template. That is, you're not taking in advantage the PreferenceForm class you just made.

So, inside the tutors.html, write this:

<form method="post">{% csrf_token %}
    {{ form }}
    <input type="submit" name="submit_preference">
</form>

But this will not work alone. You must pass the form variable from the pref2 view to your template (in order for {{ form }} to be populated).

Change to:

return render(request, 'website/tutors.html', locals())

Also, the

prefer = form.save(commit=False)
prefer.save()

is reduntant. Since there is no data manipulation between these two lines (i.e you're not modifying the prefer form in some way), you can just make it one, like this:

prefer = form.save()

Upvotes: 1

Related Questions