为什么Django会在此表单验证中抛出KeyError?

时间:2013-03-13 20:49:25

标签: django django-models django-forms

以下是代码:

...

class Meta:
    model = Card

def clean_video_url(self):
    video_url = self.cleaned_data['video_url']
    if video_url != '' and len(video_url) != YOUTUBE_VIDEO_URL_LENGTH:
        pos = string.find(video_url, YOUTUBE_VIDEO_URL_IDENTIFIER)
        identifier_length = len(YOUTUBE_VIDEO_URL_IDENTIFIER)
        if pos == -1:
            raise forms.ValidationError(_('youtube-url-not-valid'))
        video_url = video_url[pos+identifier_length:pos+identifier_length+YOUTUBE_VIDEO_URL_LENGTH]
    return video_url

...

def clean(self):
    video_url = self.cleaned_data['video_url']
    field1 = self.cleaned_data['field1']
    if video_url == '' and field1 == '':
        raise forms.ValidationError(_('must-fill-video-url-or-front'))
    return self.cleaned_data

最令人不安的是,它几乎适用于所有情况下(在数据库中提交并保留)。当我在 video_url字段中编写像'aeuchah'这样的虚拟文本时,它不起作用,而是抛出:

Exception Type: KeyError
Exception Value:    
'video_url'

我重新阅读了我的clean_video_url方法,然后看看pdb.set_trace等调试工具的变量是什么,但我找不到问题。

更新正如Marius Grigaitis和Davide R.所说,在完成所有单独的野外方法后,会调用干净的方法。 clean_video_url引发了ValidationError并且没有返回任何内容,因此clean方法没有找到任何工作并引发了KeyError。

1 个答案:

答案 0 :(得分:3)

cleaned_data方法中使用密钥之前,您应始终检查该密钥是否存在于clean()中。如果之前的验证尚未通过,则无法保证clean_data数组中存在该值。

文档:https://docs.djangoproject.com/en/dev/ref/forms/validation/#cleaning-and-validating-fields-that-depend-on-each-other

  

当调用表单的clean()方法时,将运行所有单独的字段清理方法(前两个部分),因此self.cleaned_data将填充到目前为止幸存的任何数据。因此,您还需要记住允许您想要验证的字段可能无法在最初的单个字段检查中幸存下来。