Django的is_valid()在modelformset_factory中无效

1 投票
2 回答
3256 浏览
提问于 2025-04-15 16:20

我用一个叫做modelformset_factory的工具创建了一个简单的联系表单,这个工具可以根据数据库模型在视图中生成表单。现在我遇到的问题是,在保存数据之前的is_valid()检查没有起作用。当我提交一个有空字段的表单时,它仍然通过了is_valid()的检查,并试图把数据写入数据库。

我希望当字段为空时,is_valid()检查能失败,这样用户就能看到错误信息,并被引导回表单。我觉得这个问题应该有简单的解决办法。你知道我在代码中缺少了什么吗?

谢谢。

代码:

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}

解决方案:

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

2 个回答

1

你真的想要一个 formset 吗?我觉得如果你的联系人表单里只有一个 Response 的实例,那你可能只需要一个 ModelForm...

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

至于哪些字段可以留空,哪些不可以,先确保在后台管理系统里能正常工作,然后 ModelForm 就会自动处理好这些(毕竟后台管理系统就是这么生成表单的)。

2

你的问题是,提供0个项目是一个有效的表单集合,并没有最低数量的验证。我建议你创建一个自定义的BaseModelFormset子类,在它的clean()方法中检查至少要有一个对象。

撰写回答