how to change image format when uploading image in django?
Question:
When a user uploads an image from the Django admin panel, I want to change the image format to ‘.webp’. I have overridden the save method of the model. Webp file is generated in the media/banner folder but the generated file is not saved in the database. How can I achieve that?
def save(self, *args, **kwargs):
super(Banner, self).save(*args, **kwargs)
im = Image.open(self.image.path).convert('RGB')
name = 'Some File Name with .webp extention'
im.save(name, 'webp')
self.image = im
But After saving the model, instance of the Image class not saved in the database?
My Model Class is :
class Banner(models.Model):
image = models.ImageField(upload_to='banner')
device_size = models.CharField(max_length=20, choices=Banner_Device_Choice)
Answers:
from django.core.files import ContentFile
If you already have the webp file, read the webp file, put it into the ContentFile()
with a buffer (something like io.BytesIO
). Then you can proceed to save the ContentFile()
object to a model. Do not forget to update the model field, and save the model!
https://docs.djangoproject.com/en/4.1/ref/files/file/
Alternatively
"django-webp-converter is a Django app which straightforwardly converts static images to WebP images, falling back to the original static image for unsupported browsers."
It might have some save capabilities too.
https://django-webp-converter.readthedocs.io/en/latest/
The cause
You are also saving in the wrong order, the correct order to call the super().save()
is at the end.
Edited, and tested solution:
from django.core.files import ContentFile
from io import BytesIO
def save(self, *args, **kwargs):
#if not self.pk: #Assuming you don't want to do this literally every time an object is saved.
img_io = BytesIO()
im = Image.open(self.image).convert('RGB')
im.save(img_io, format='WEBP')
name="this_is_my_webp_file.webp"
self.image = ContentFile(img_io.getvalue(), name)
super(Banner, self).save(*args, **kwargs) #Not at start anymore
hello do it like this:
...
from django.db.models.signals import post_save
from django.dispatch import receiver
class Banner(models.Model):
image = models.ImageField(upload_to='banner')
device_size = models.CharField(max_length=20,choices=Banner_Device_Choice)
@receiver(post_save, sender=Banner)
def create_webp(sender, instance, created, **kwargs):
path = instance.image.path
if instance.image.path[-4:] !=webp:
im = Image.open(path).convert('RGB')
extention = instance.image.path.rsplit(".",2)[1]
file_name = path.replace(extention,"webp")
im.save(file_name, 'webp')
instance.image.path = file_name
instance.save()
When a user uploads an image from the Django admin panel, I want to change the image format to ‘.webp’. I have overridden the save method of the model. Webp file is generated in the media/banner folder but the generated file is not saved in the database. How can I achieve that?
def save(self, *args, **kwargs):
super(Banner, self).save(*args, **kwargs)
im = Image.open(self.image.path).convert('RGB')
name = 'Some File Name with .webp extention'
im.save(name, 'webp')
self.image = im
But After saving the model, instance of the Image class not saved in the database?
My Model Class is :
class Banner(models.Model):
image = models.ImageField(upload_to='banner')
device_size = models.CharField(max_length=20, choices=Banner_Device_Choice)
from django.core.files import ContentFile
If you already have the webp file, read the webp file, put it into the ContentFile()
with a buffer (something like io.BytesIO
). Then you can proceed to save the ContentFile()
object to a model. Do not forget to update the model field, and save the model!
https://docs.djangoproject.com/en/4.1/ref/files/file/
Alternatively
"django-webp-converter is a Django app which straightforwardly converts static images to WebP images, falling back to the original static image for unsupported browsers."
It might have some save capabilities too.
https://django-webp-converter.readthedocs.io/en/latest/
The cause
You are also saving in the wrong order, the correct order to call the super().save()
is at the end.
Edited, and tested solution:
from django.core.files import ContentFile
from io import BytesIO
def save(self, *args, **kwargs):
#if not self.pk: #Assuming you don't want to do this literally every time an object is saved.
img_io = BytesIO()
im = Image.open(self.image).convert('RGB')
im.save(img_io, format='WEBP')
name="this_is_my_webp_file.webp"
self.image = ContentFile(img_io.getvalue(), name)
super(Banner, self).save(*args, **kwargs) #Not at start anymore
hello do it like this:
...
from django.db.models.signals import post_save
from django.dispatch import receiver
class Banner(models.Model):
image = models.ImageField(upload_to='banner')
device_size = models.CharField(max_length=20,choices=Banner_Device_Choice)
@receiver(post_save, sender=Banner)
def create_webp(sender, instance, created, **kwargs):
path = instance.image.path
if instance.image.path[-4:] !=webp:
im = Image.open(path).convert('RGB')
extention = instance.image.path.rsplit(".",2)[1]
file_name = path.replace(extention,"webp")
im.save(file_name, 'webp')
instance.image.path = file_name
instance.save()