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 ?

Chaitanya Patel
  • 390
  • 1
  • 4
  • 15

2 Answers2

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/

Community
  • 1
  • 1
Aniket Pawar
  • 2,641
  • 19
  • 32
  • 2
    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"` – Rob L Jun 20 '17 at 13:35
  • This only worked when I did if str(filetype) != "application/csv": raise ValidationError("File is not a CSV file.") – JessicaRyan Apr 02 '22 at 11:05
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.