3

I have a model containing file field. I want to restrict it to pdf files. I have written clean method in model because I want to check for admin and shell level model creation also. But it is not working in model clean method. However form clean method is working.

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

If I upload pdf, mime in form clean method is correctly validating (printing 'application/pdf'). But model clean method is not validating. It is printing mime as 'application/x-empty'. Where am I doing wrong ?

Also one more problem is that if model clean method raise validation error, it is not shown as field error in form, but it is showing as non-field errors. Why so ?

2 Answers 2

3

Since you are using form validation you are not to be worry about model clean method

You are already doing correct thing in form

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

If you want to use model clean you can make your own validator

https://stackoverflow.com/a/27916582/5518973

You are using server side python-django validation but javascript is also nice way for validating file client side.For javascript regex validation you can look out for this answer

https://stackoverflow.com/a/17067242/5518973

or if you are able to use plugins you can use jquery validation plugin

https://jqueryvalidation.org/

Sign up to request clarification or add additional context in comments.

2 Comments

Unfortunately, the above code won't work. filetype will be something like 'PDF document, version 1.3'. You'll need the assignment to be filetype = magic.from_buffer(yourfile.read(), mime=True) in order to get "application/pdf"
This only worked when I did if str(filetype) != "application/csv": raise ValidationError("File is not a CSV file.")
0
fields = '__all__'

A suggestion from Two Scoops of Django: Best Practices for Django 1.8

26.14 Don't Use ModelForms.Meta.fields = "__ all __" - This includes every model field in your model form. It’s a shortcut, and a dangerous one. It’s very similar to what we describe in section 26.13 (Don't Use ModelForms.Meta.exclude) and even with custom validation code, exposes projects to form-based Mass Assignment Vulnerabilities. We advocate avoiding this technique as much as possible, as we feel that it’s simply impossible to catch all variations of input.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.