Login

Custom FileField with content type and size validation

Author:
nemesis
Posted:
September 24, 2010
Language:
Python
Version:
1.2
Score:
1 (after 3 ratings)
 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
# extra.py in yourproject/app/

from django.db.models import FileField
from django.forms import forms
from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext_lazy as _

class ContentTypeRestrictedFileField(FileField):
    """
    Same as FileField, but you can specify:
        * content_types - list containing allowed content_types. Example: ['application/pdf', 'image/jpeg']
        * max_upload_size - a number indicating the maximum file size allowed for upload.
            2.5MB - 2621440
            5MB - 5242880
            10MB - 10485760
            20MB - 20971520
            50MB - 5242880
            100MB 104857600
            250MB - 214958080
            500MB - 429916160
    """
    def __init__(self, *args, **kwargs):
        self.content_types = kwargs.pop("content_types")
        self.max_upload_size = kwargs.pop("max_upload_size")

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

    def clean(self, *args, **kwargs):
        data = super(ContentTypeRestrictedFileField, self).clean(*args, **kwargs)

        file = data.file
        content_type = file.content_type

        if content_type in self.content_types:
            if file._size > self.max_upload_size:
                raise forms.ValidationError(_('Please keep filesize under %s. Current filesize %s') % (filesizeformat(self.max_upload_size), filesizeformat(file._size)))
        else:
            raise forms.ValidationError(_('Filetype not supported.'))

        return data

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, 7 months ago

Comments

nemesis (on September 27, 2010):

Thanks for the info.

Is not exactly a duplicated of 1303, even if I used the main part of that. 1303 is a custom validation while this is a custom file field that can be used in the admin too.

How would you advice to implement the method you linked?

#

gsakkis (on September 27, 2010):

I'd love to be proven wrong but I believe there is no way to get a nice validation error without uploading the whole file; otherwise the browser throws "The connection to the server was reset while the page was loading" on Firefox (or "Error 101 (net::ERR_CONNECTION_RESET): Unknown error" on Chrome).

#

nemesis (on September 30, 2010):

So would it be possible then to add a line in the end that deletes the file? I'll try it out..

#

nemesis (on September 30, 2010):

The files is stored only in the temporary directory.

I think it's a good solution to use both this filefield and set FILE_UPLOAD_MAX_MEMORY_SIZE in your settings.py file so it allows a size that is slight larger than the model field.

#

byroncorrales (on October 1, 2010):

For get it work with south migrations I had to changed some lines...

def __init__(self, content_types=None, max_upload_size=None, **kwargs):
    self.content_types = content_types
    self.max_upload_size = max_upload_size
    super(ContentTypeRestrictedFileField, self).__init__(**kwargs)

And adding the specific rule for south and the end of the file

from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^app\.extra\.ContentTypeRestrictedFileField"])

#

eos87 (on October 4, 2010):

it works for me!, but i recommend add the project name to the instrospection_rule path, something like this:

from south.modelsinspector import add_introspection_rules add_introspection_rules([], ["^project_name.app.extra.ContentTypeRestrictedFileField"])

#

eos87 (on October 4, 2010):

oops! i forgot the slashes!!

from south.modelsinspector import add_introspection_rules
add_introspection_rules([], ["^project_name\.app\.extra\.ContentTypeRestrictedFileField"])

#

nemesis (on October 30, 2010):

@gsakkis

I designed this field to use it in the admin so i'm not worried about 1GB file because the users are already trusted.

For who's worried about huge files: configure the max upload limit in apache.

#

sv1jsb (on February 18, 2011):

I am new in Django but I would like to ask this, reading your code.

You import FileField from models but FileField in models doesn't have a clean method.

FileField from forms have one.

You have been using this snippet as it is and it worked without a problem?

#

dokterbob (on August 31, 2011):

A new & dusted off version, checking minimum size, maximum size, matching extensions and mime types.

https://gist.github.com/1183767

#

AguirreLORETTA27 (on March 14, 2012):

Some time ago, I needed to buy a building for my business but I didn't have enough cash and could not purchase anything. Thank heaven my father proposed to try to take the loans at banks. Thus, I acted so and was satisfied with my collateral loan.

#

Please login first before commenting.