FileField with file extension whitelist

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import os

from django import forms


class ExtFileField(forms.FileField):
    """
    Same as forms.FileField, but you can specify a file extension whitelist.
    
    >>> from django.core.files.uploadedfile import SimpleUploadedFile
    >>>
    >>> t = ExtFileField(ext_whitelist=(".pdf", ".txt"))
    >>>
    >>> t.clean(SimpleUploadedFile('filename.pdf', 'Some File Content'))
    >>> t.clean(SimpleUploadedFile('filename.txt', 'Some File Content'))
    >>>
    >>> t.clean(SimpleUploadedFile('filename.exe', 'Some File Content'))
    Traceback (most recent call last):
    ...
    ValidationError: [u'Not allowed filetype!']
    """
    def __init__(self, *args, **kwargs):
        ext_whitelist = kwargs.pop("ext_whitelist")
        self.ext_whitelist = [i.lower() for i in ext_whitelist]

        super(ExtFileField, self).__init__(*args, **kwargs)

    def clean(self, *args, **kwargs):
        data = super(ExtFileField, self).clean(*args, **kwargs)
        filename = data.name
        ext = os.path.splitext(filename)[1]
        ext = ext.lower()
        if ext not in self.ext_whitelist:
            raise forms.ValidationError("Not allowed filetype!")

#-------------------------------------------------------------------------

if __name__ == "__main__":
    import doctest, datetime
    doctest.testmod()

More like this

  1. Whitelisted overwriting FileSystemStorage by nickma_at 6 months ago
  2. Amazon S3 Enabled FileField and ImageField (with Boto) by natebeacham 1 year, 10 months ago
  3. Custom FileField with content type and size validation by nemesis 1 year, 4 months ago
  4. Add a "remove file" field for Image- or FileFields by rodrigoc 3 years, 6 months ago
  5. Human readable file names decorator by maxk 10 months, 1 week ago

Comments

Finity (on May 23, 2011):

This will through an AttributeError if required=False. (Due to trying to access data.name when data will be None if required == False).

I rewrote it as [HTML_REMOVED] def clean(self, *args, kwargs): data = super(ExtFileField, self).clean(*args, kwargs)

    if data is None:
        if self.required:
            raise ValidationError("This file is required")
        else:
            return
    else:
        filename = data.name
        ext = os.path.splitext(filename)[1]
        ext = ext.lower()
        if ext not in self.ext_whitelist:
            file_types = ", ".join([i for i in self.ext_whitelist])
            error = "Only allowed file types are: %s" % file_types
            raise forms.ValidationError(error)

[HTML_REMOVED]

Hopefully I'm correct on this one.

#

Finity (on May 23, 2011):

s/through/raise an AttributeError exception. :)

Couldn't figure out how to keep djangosnippets from mucking up my code, but hopefully you get the point.

#

(Forgotten your password?)