How to limit file types on file uploads for ModelForms with FileFields?

Viewed 31266

My goal is to limit a FileField on a Django ModelForm to PDFs and Word Documents. The answers I have googled all deal with creating a separate file handler, but I am not sure how to do so in the context of a ModelForm. Is there a setting in settings.py I may use to limit upload file types?

8 Answers

Django since 1.11 has a FileExtensionValidator for this purpose:

class SomeDocument(Model):
    document = models.FileFiled(validators=[
        FileExtensionValidator(allowed_extensions=['pdf', 'doc'])])

As @savp mentioned, you will also want to customize the widget so that users can't select inappropriate files in the first place:

class SomeDocumentForm(ModelForm):
    class Meta:
        model = SomeDocument
        widgets = {'document': FileInput(attrs={'accept': 'application/pdf,application/msword'})}
        fields = '__all__'

You may need to fiddle with accept to figure out exactly what MIME types are needed for your purposes.

As others have mentioned, none of this will prevent someone from renaming badstuff.exe to innocent.pdf and uploading it through your form—you will still need to handle the uploaded file safely. Something like the python-magic library can help you determine the actual file type once you have the contents.

I find that the best way to check the type of a file is by checking its content type. I will also add that one the best place to do type checking is in form validation. I would have a form and a validation as follows:

class UploadFileForm(forms.Form):
    file = forms.FileField()

    def clean_file(self):
        data = self.cleaned_data['file']

        # check if the content type is what we expect
        content_type = data.content_type
        if content_type == 'application/pdf':
            return data
        else:
            raise ValidationError(_('Invalid content type'))

The following documentation links can be helpful: https://docs.djangoproject.com/en/3.1/ref/files/uploads/ and https://docs.djangoproject.com/en/3.1/ref/forms/validation/

Related