-
-
Save frnhr/65b64df781c07de2ce77ca84f5c12f15 to your computer and use it in GitHub Desktop.
A form field to handle validation of image + svg, Django 3.1
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from django.core import validators | |
from lxml import etree | |
from django.core.exceptions import ValidationError | |
from django.forms import ImageField | |
# monkeypatch allowed file extensions: | |
_original = validators.get_available_image_extensions | |
validators.get_available_image_extensions = lambda: _original() + ["svg"] | |
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. | |
""" | |
file = super(ImageField, self).to_python(data) # skip a MRO level | |
if file is None: | |
return None | |
try: | |
file = super().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().run_validators(value) | |
@staticmethod | |
def is_svg(file): | |
"""Check if the provided file is a SVG image.""" | |
if file is None: | |
return False | |
if hasattr(file, 'seek'): | |
file.seek(0) | |
opened = False | |
else: | |
file = open(file) | |
opened = True | |
try: | |
part_of_svg_tag = '{http://www.w3.org/2000/svg}' | |
tree = etree.iterparse(file) | |
first_tag = next(tree)[1].tag | |
return part_of_svg_tag in first_tag | |
except etree.ParseError: | |
return False | |
finally: | |
if opened: | |
file.close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment