Skip to content

Instantly share code, notes, and snippets.

@chrisidakwo
Forked from moskrc/validators.py
Created August 31, 2018 11:54
Show Gist options
  • Save chrisidakwo/3021b649202fce4dc1ed30cfd0fc8133 to your computer and use it in GitHub Desktop.
Save chrisidakwo/3021b649202fce4dc1ed30cfd0fc8133 to your computer and use it in GitHub Desktop.
Validator for files, checking the size, extension and mimetype. Modified to work with Django 2.0.6 and Python 3.6.4
from os.path import splitext
import mimetypes
from django.core.exceptions import ValidationError
from django.template.defaultfilters import filesizeformat
from django.utils.translation import ugettext_lazy as _
from django.utils.deconstruct import deconstructible
@deconstructible
class FileValidator(object):
"""
Validator for files, checking the size, extension and mimetype.
Modified to work with Django 2.0.6 and Python 3.6.4
Initialization parameters:
allowed_extensions: iterable with allowed file extensions
ie. ('txt', 'doc')
allowd_mimetypes: iterable with allowed mimetypes
ie. ('image/png', )
min_size: minimum number of bytes allowed
ie. 100
max_size: maximum number of bytes allowed
ie. 24*1024*1024 for 24 MB
Usage example::
MyModel(models.Model):
myfile = FileField(validators=FileValidator(max_size=24*1024*1024), ...)
"""
extension_message = _("Extension '%(extension)s' not allowed. Allowed extensions are: '%(allowed_extensions)s.'")
mime_message = _("MIME type '%(mimetype)s' is not valid. Allowed types are: %(allowed_mimetypes)s.")
min_size_message = _('The current file %(size)s, which is too small. The minumum file size is %(allowed_size)s.')
max_size_message = _('The current file %(size)s, which is too large. The maximum file size is %(allowed_size)s.')
def __init__(self, *args, **kwargs):
self.allowed_extensions = kwargs.pop('allowed_extensions', None)
self.allowed_mimetypes = kwargs.pop('allowed_mimetypes', None)
self.min_size = kwargs.pop('min_size', 0)
self.max_size = kwargs.pop('max_size', None)
def __call__(self, value):
"""
Check the extension, content type and file size.
"""
# Check the extension
ext = splitext(value.name)[1][1:].lower()
if self.allowed_extensions and ext not in self.allowed_extensions:
message = self.extension_message % {
'extension': ext,
'allowed_extensions': ', '.join(self.allowed_extensions)
}
raise ValidationError(message)
# Check the content type
mimetype = mimetypes.guess_type(value.name)[0]
if self.allowed_mimetypes and mimetype not in self.allowed_mimetypes:
message = self.mime_message % {
'mimetype': mimetype,
'allowed_mimetypes': ', '.join(self.allowed_mimetypes)
}
raise ValidationError(message)
# Check the file size
filesize = len(value)
if self.max_size and filesize > self.max_size:
message = self.max_size_message % {
'size': filesizeformat(filesize),
'allowed_size': filesizeformat(self.max_size)
}
raise ValidationError(message)
elif filesize < self.min_size:
message = self.min_size_message % {
'size': filesizeformat(filesize),
'allowed_size': filesizeformat(self.min_size)
}
raise ValidationError(message)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment