views:

381

answers:

2

I've created a simple contact form using the modelformset_factory to build the form in the view using the DB model. The issue that I am having is that the is_valid() check before the save() is not working. When I submit the form with empty fields it still passes the is_valid() and attempts to write to the DB.

I would like the is_valid() check to fail when the fields are empty so that the user can be directed to the form again with an error message. I believe that there is a simple solution to this. Do you know what I am missing in my code?

Thanks.

Code:

models.py

class Response(models.Model):
    name = models.CharField(max_length=50,verbose_name='Your Name:')
    email = models.CharField(max_length=50,verbose_name='Email:')
    phone = models.CharField(max_length=50,verbose_name='Phone Number:')
    apt_size = models.CharField(max_length=25,
                                choices=APT_CHOICES,
                                verbose_name='Apt Size:')
    movein_at= models.DateField(verbose_name='Desired Move-In Date')
    community = models.CharField(max_length=50,
                                 choices=COMMUNITY_CHOICES,
                                 verbose_name='Community You Are Interested In:')
    referred_by = models.CharField(max_length=50,
                                   choices=REFERRED_CHOICES,
                                   verbose_name='Found Us Where?')
    referred_other = models.CharField(blank=True,max_length=50,verbose_name='If Other:')
    comments = models.TextField(verbose_name='Comments:')
    created_at = models.DateTimeField(auto_now_add=True)
    def __unicode__(self):
        return self.name

views.py

from summitpark.contact.models import * 
from django.shortcuts import render_to_response
from django.forms.models import modelformset_factory

def form(request):
    contact_form_set = modelformset_factory(Response,fields=('name','email','phone',
                                                            'apt_size','movein_at',
                                                            'community','referred_by',
                                                            'comments'),
                                                    exclude=('id'))
    if request.method == 'POST':
        formset = contact_form_set(request.POST)
        if formset.is_valid():
            formset.save()
            return render_to_response('contact/confirm.html')
        else: 
            return render_to_response('contact/form.html',{'formset':formset})
    else:
        formset = contact_form_set(queryset=Response.objects.none())
        return render_to_response('contact/form.html',{'formset':formset}

Solution:

class BaseContactFormSet(BaseModelFormSet):
def clean(self):
    if any(self.errors):
        return
    for form in self.forms:
        name = form['name'].data
        if not name:
            raise forms.ValidationError, "Please Complete the Required Fields
+1  A: 

Your issue is that providing 0 items is a valid formset, there is no minimum validation. I'd provide a custom BaseModelFormset subclass that's clean() method just checked for a minimum of one obj.

Alex Gaynor
Your solution worked but I am not able to display the error messages in the view. Any ideas?
markkoberlein
I realized I wasn't displaying {{ formset.non_form_errors }} in the view. Thanks for your help.
markkoberlein
A: 

Did you really want a formset? I suspect if you have a contacts form with only one instance of the Response in then you want a ModelForm...

class ResponseForm(forms.ModelForm):
    class Meta:
        model = Response
        fields=('name','email','phone',
               'apt_size','movein_at',
               'community','referred_by',
               'comments')

As for which fields are allowed to be blank and which aren't, make sure it does the right thing in the admin first, then the ModelForm will do exactly the right thing (that is how the admin makes its forms after all).

Nick Craig-Wood