Skip to content

Instantly share code, notes, and snippets.

Created February 26, 2016 10:24
Show Gist options
  • Save ambivalentno/9bc42b9a417677d96a21 to your computer and use it in GitHub Desktop.
Save ambivalentno/9bc42b9a417677d96a21 to your computer and use it in GitHub Desktop.
A form field to handle validation of image + svg.
import sys
from io import BytesIO
from PIL import Image
import xml.etree.cElementTree as et
from django.core.exceptions import ValidationError
from django.forms import ImageField as DjangoImageField
from django.utils import six
class SVGAndImageFormField(DjangoImageField):
def to_python(self, data):
Checks that the file-upload field data contains a valid image (GIF, JPG,
PNG, possibly others -- whatever the Python Imaging Library supports).
test_file = super(DjangoImageField, self).to_python(data)
if test_file is None:
return None
# We need to get a file object for Pillow. We might have a path or we might
# have to read the data into memory.
if hasattr(data, 'temporary_file_path'):
ifile = data.temporary_file_path()
if hasattr(data, 'read'):
ifile = BytesIO(
ifile = BytesIO(data['content'])
# load() could spot a truncated JPEG, but it loads the entire
# image in memory, which is a DoS vector. See #3848 and #18520.
image =
# verify() must be called immediately after the constructor.
# Annotating so subclasses can reuse it for their own validation
test_file.image = image
test_file.content_type = Image.MIME[image.format]
except Exception:
# add a workaround to handle svg images
if not self.is_svg(ifile):
six.reraise(ValidationError, ValidationError(
), sys.exc_info()[2])
if hasattr(test_file, 'seek') and callable(
return test_file
def is_svg(self, f):
Check if provided file is svg
tag = None
for event, el in et.iterparse(f, ('start',)):
tag = el.tag
except et.ParseError:
return tag == '{}svg'
Copy link

In line 44 ifile can be a filepath. Then when it is passed to is_svg it blows up, cause it tries to launch seek method on string object. Need to open this file before seek.

Copy link

ruchej commented Jan 12, 2020

Dont work on django 3
from django.utils import six

Copy link

Copy link

ramsrib commented Jun 22, 2020

In latest version of django, you need to update the exception like this (replace line 45-48):

raise ValidationError(

Copy link

ramsrib commented Jun 22, 2020

Also you need to add default validator to this form field to make it work in Django 3. Refer this:

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment