在django表单中捕获验证错误

时间:2012-01-25 21:52:05

标签: django django-forms

我有两种模式:

class Studio(models.Model):
    name = models.CharField("Studio", max_length=30, unique=True)

class Film(models.Model):
    studio = models.ForeignKey(Studio, verbose_name="Studio")
    name = models.CharField("Film Name", max_length=30, unique=True)

我有一个电影表单,允许用户选择一个预先存在的Studio,或者输入一个新表单(在earlier question的帮助下:

class FilmForm(forms.ModelForm):
    required_css_class = 'required'
    studio = forms.ModelChoiceField(Studio.objects, required=False, widget = SelectWithPlus)
    new_studio = forms.CharField(max_length=30, required=False, label = "New Studio Name", widget = DeSelectWithX(attrs={'class' : 'hidden_studio_field'}))

    def __init__(self, *args, **kwargs):
        super(FilmForm, self).__init__(*args,**kwargs)
        self.fields['studio'].required = False

    def clean(self):
        cleaned_data = self.cleaned_data
        studio = cleaned_data.get('studio')
        new_studio = cleaned_data.get('new_studio')

        if not studio and not new_studio:
            raise forms.ValidationError("Must specify either Studio or New Studio!")
        elif not studio:
            studio, created = Studio.objects.get_or_create(name = new_studio)
            self.cleaned_data['studio'] = studio

        return super(FilmForm,self).clean()

    class Meta:
        model = Film

现在,我的第一个问题是当studio和new_studio都缺失时我得到一个django ValueError:无法分配无:“Film.studio”不允许空值错误。我以为我是捕获所有错误,因此django应该永远不会实现Film.studio是空的。

第二个问题是操作顺序。 如果我想在我确定FilmForm的其余部分有效之后才想保存new_studio怎么办(这样可以防止在完整的电影条目通过之前保存一堆工作室名称)?我是明确的还是我冒着过早保存的风险,因为new_studio被保存在表格的清洁中?

修改:添加了Traceback并编辑了验证if-statements

2 个答案:

答案 0 :(得分:2)

从cleaning_data删除工作室 new_studio

    if not studio and not new_studio:
        del cleaned_data['studio'], cleaned_data['new_studio']
        raise forms.ValidationError("Must specify either Studio or New Studio!")

答案 1 :(得分:1)

关于防止new_studio投降的费用:

新的def清洁形式:     def clean(self):         cleaning_data = self.cleaned_data         studio = cleaning_data.get('studio')         new_studio = cleaning_data.get('new_studio')

    if not studio and not new_studio:
        del cleaned_data['studio'], cleaned_data['new_studio']
        raise forms.ValidationError("Must specify either Studio or New Studio!")
    elif not studio:
        del cleaned_data['studio']

    return super(FilmForm,self).clean()

在视图中:

def testone(request):
    if request.method == 'POST': # If the form has been submitted...
        form = FilmForm(request.POST) # A form bound to the POST data

        if form.is_valid(): # All validation rules pass
            if form.cleaned_data['new_studio']:
                studio, created = Studio.objects.get_or_create(name = form.cleaned_data['new_studio'])
                new_film = form.save(commit=False)
                new_film.studio = studio
            else:
                new_film = form

            new_film.save()
            return HttpResponseRedirect('/') # Redirect after POST
        else:
            form = FilmForm() # An unbound form

        return render_to_response('testone.html', {
            'form': form
        }, context_instance=RequestContext(request))