(Django)覆盖clean_field或添加模型验证器中断保存?

时间:2014-07-25 17:34:40

标签: django forms validation django-forms

我正在尝试为Django ModelForm添加一些验证,但我正在以某种方式破坏保存。我有一个带有FileField的模型,我希望FileField只接受PDF。

我写了一个验证函数:

def validate_pdf(value):
    if not value.name.endswith('pdf'):
        raise ValidationError(u'Invalid File')

我将它附加到我的模型的FileField:

class MediaObject(models.Model):
    ...
    pdf = models.FileField(upload_to='pdfs', blank=True, validators=[validate_pdf])

然后,当我使用我之前使用的功能型ModelForm时,我能够选择一个文件,但该文件未在提交时上传或保存到模型中。它表现得好像我根本没有选择任何文件。如果我没有选择文件,表单的其余部分工作正常。如果我确实选择了一个文件,那么除了保存文件之外,其他表单也无法保存。

我删除了验证器并且表单恢复正常工作,但显然没有我想要的验证器。我尝试转到表单并覆盖每个字段的clean方法,并且表单的整体清理,但结果每次都相同 - 使用附加了验证器的任何字段都会破坏保存。

我是否遗漏了将验证器附加到文件字段的内容?


(旁白:我知道查看文件扩展名是一种验证文件类型的愚蠢方法。我打算扩展验证器以查看mimetype,但正如他们所说,在你运行之前走路。)


在某些视图处理中编辑以帮助诊断问题:

@user_passes_test(p_restricted)
def pDashCTSCBook(request, *args, **kwargs):

    user = request.user
    mo = MediaObject.objects.get(id=request.GET.get('id'))
    if request.method == 'POST':
        form = pCTSCForm(request.POST, request.FILES, instance=mo)
        if form.is_valid():
            tsc = form.save()
            form.save_m2m()
            return HttpResponseRedirect('/successpage/')

    else:
        form = pCTSCForm(instance=mo)

    return render_to_response('dir/template.html', {'mo': mo, 'user': user, 'form': form}, context_instance=RequestContext(request))

经过更多的讨论,我可以自信地说,问题是ValidationError永远不会被引发。调用第一个form.is_valid(),检查验证器,如果测试失败,则出现问题 - 而不是停止并引发错误,它会一直尝试保存无效表单。如果验证器通过但是一切正常。我尝试从django.forms和django.core.exceptions获取ValidationError,结果相同。

如果我进入验证器并将其更改为以下内容:

def validate_pdf(value):
   if not value.name.endswith('pdf'):
       return ValidationError(u'Invalid File') #note return rather than raise
   return value

只要我尝试上传PDF,一切正常。但是,如果我尝试上传其他内容,我会收到AttributeError: ValidationError object has no attribute '_committed'

当表单命中form.save()时会引发此AttributeError,这告诉我即使验证程序正在执行其工作并且正在执行if not value.name.endswith('pdf')下面的代码,但错误未被引发。< / p>

1 个答案:

答案 0 :(得分:0)

尝试使用此功能(可能验证器在考虑字段有效之前需要一些返回值):

def validate_pdf(value):
    if not value.name.endswith('pdf'):
        raise ValidationError(u'Invalid File')
    return