Login

FileField with file extension whitelist

Author:
jedie
Posted:
August 14, 2008
Language:
Python
Version:
.96
Score:
2 (after 6 ratings)

A simple FileField with a addition file extension whitelist. Raised ValidationError("Not allowed filetype!") if a filename contains a extension witch is not in the 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. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 8 months 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 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)

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.

#

computmaxer (on February 19, 2013):

This snippet does not account for a field that is not required, and also does not return data so it does not get cleaned correctly.

The superclass will return False for data if the file has been cleared and the field is not required.

Here's a revised clean method for this snippet:

```

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

```

#

Please login first before commenting.