Django:使用python magic在模型中验证文件字段

Django:使用python magic在模型中验证文件字段,django,django-models,django-file-upload,python-magic,Django,Django Models,Django File Upload,Python Magic,我有一个包含文件字段的模型。我想把它限制为pdf文件。我在模型中编写了clean方法,因为我还想检查管理和shell级别的模型创建。但它在模型清洁方法中不起作用。然而,表单清理方法正在发挥作用 class mymodel(models.Model): myfile = models.FileField() def clean(): mime = magic.from_buffer(self.myfile.read(), mime=True) pr

我有一个包含文件字段的模型。我想把它限制为pdf文件。我在模型中编写了clean方法,因为我还想检查管理和shell级别的模型创建。但它在模型清洁方法中不起作用。然而,表单清理方法正在发挥作用

class mymodel(models.Model):
    myfile = models.FileField()

    def clean():
        mime = magic.from_buffer(self.myfile.read(), mime=True)
        print mime
        if not mime == 'application/pdf':
            raise ValidationError('File must be a PDF document')

class myform(forms.ModelForm):
    class Meta:
        model = mymodel
        fields = '__all__'

    def clean_myfile(self):
        file = self.cleaned_data.get('myfile')
        mime = magic.from_buffer(file.read(), mime=True)
        print mime
        if not mime == 'application/pdf':
            raise forms.ValidationError('File must be a PDF document')
        else:
            return file
如果我上传pdf,则form clean方法中的mime正在正确验证(打印“应用程序/pdf”)。但模型清理方法并没有验证。它正在将mime打印为“application/x-empty”。我哪里做错了


还有一个问题是,若模型清理方法引发验证错误,它在表单中不会显示为字段错误,而是显示为非字段错误。为什么会这样?

因为您使用的是表单验证,所以不必担心模型清理方法

你已经在做正确的事情了

def clean_file(self):
        yourfile = self.cleaned_data.get("your_filename_on_template", False)
        filetype = magic.from_buffer(yourfile.read())
        if not "application/pdf" in filetype:
            raise ValidationError("File is not PDF.")
        return yourfile
如果您想使用ModelClean,您可以创建自己的验证器

您正在使用服务器端python django验证,但javascript也是验证文件客户端的好方法

或者,如果您能够使用插件,您可以使用jquery验证插件

来自两大勺Django的建议:Django 1.8的最佳实践

26.14不要使用ModelForms.Meta.fields=“\uuuuuuu所有\uuuuuuu”-这包括模型表单中的每个模型字段。这是一条捷径,也是一条危险的捷径。 它与我们在第26.13节中描述的非常相似(不要使用ModelForms.Meta.exclude),甚至与 自定义验证代码,将项目公开给基于表单的批量分配 脆弱性。我们主张尽量避免使用这种技术 可能,因为我们觉得根本不可能抓住一切 输入的变化


不幸的是,上面的代码不起作用<代码>文件类型类似于“PDF文档,1.3版”。您需要将赋值设置为
filetype=magic.from_buffer(yourfile.read(),mime=True)
才能获取
“application/pdf”
fields = '__all__'