Skip to content

Instantly share code, notes, and snippets.

@ObserverOfTime
Forked from ambivalentno/svgimagefield.py
Last active October 28, 2020 16:55
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save ObserverOfTime/1a035e3a65e08aa5146eb120396d18ee to your computer and use it in GitHub Desktop.
Save ObserverOfTime/1a035e3a65e08aa5146eb120396d18ee to your computer and use it in GitHub Desktop.
A form field to handle validation of image + svg.
from xml.etree import cElementTree as et
from django.core.exceptions import ValidationError
from django.forms import ImageField
class SVGImageField(ImageField):
"""A Django ImageField that accepts SVG images."""
def to_python(self, data):
"""
Check that the file-upload field data contains a valid image
(GIF, JPG, PNG, etc. -- whatever Pillow supports) or a SVG image.
"""
try:
file = super(SVGImageField, self).to_python(data)
except ValidationError as err:
# add a workaround to handle svg images
if not self.is_svg(file):
raise ValidationError(
self.error_messages['invalid_image'],
code='invalid_image',
) from err
file = super(ImageField, self).to_python(data)
file.content_type = 'image/svg+xml'
return file
def run_validators(self, value: str):
if not self.is_svg(value):
return super(ImageField, self).run_validators(value)
return super(SVGImageField, self).run_validators(value)
@staticmethod
def is_svg(file):
"""Check if the provided file is a SVG image."""
file = file.seek(0) if hasattr(file, 'seek') else open(file)
try:
tag = '{http://www.w3.org/2000/svg}svg'
iter = et.iterparse(file, ('start',))
return next(iter)[1].tag == tag
except et.ParseError:
return False
finally:
file.close()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment