Django save overrides ImageField processing

After the problems that I had on this thread , there is still a big problem in my models.py when I use Django Admin. Here is my code (I removed material not related to my problem):

from django.core.files.uploadedfile import InMemoryUploadedFile from PIL import Image as Img import StringIO class Mymodel(models.Model): photo = models.ImageField(upload_to="photo/", blank=True, null=True) def save(self, *args, **kwargs): width = 500 height = 500 size = (width,height) if self.photo: image = Img.open(StringIO.StringIO(self.photo.read())) (imw, imh) = image.size if (imw>width) or (imh>height) : image.thumbnail(size, Img.ANTIALIAS) #If RGBA, convert transparency if image.mode == "RGBA": image.load() background = Img.new("RGB", image.size, (255, 255, 255)) background.paste(image, mask=image.split()[3]) #3 is alpha channel image=background output = StringIO.StringIO() image.save(output, format='JPEG', quality=60) output.seek(0) self.photo = InMemoryUploadedFile(output,'ImageField', "%s.jpg" %self.photo_principale.name.split('.')[0], 'image/jpeg', output.len, None) try: this = Mymodel.objects.get(id=self.id) if this.photo != self.photo: this.photo.delete(save=False) except: pass # when new photo then we do nothing, normal case super(Mymodel, self).save(*args, **kwargs) 

It works, files are downloaded, modified and converted to JPEG if necessary. The problem is, every time I edit it, even when it DOES NOT load a new image, it creates a new image (for example, I first save my model with the image "hello.jpg", then I edit it, this will create a new image called "hello_1 .jpg ", even if I didn’t download anything). I thought the try / except block would only work when editing (so there is no new file download), but apparently not.

Thanks in advance for your help:)

+1
source share
2 answers

Final solution working for me:

 from django.core.files.uploadedfile import InMemoryUploadedFile from PIL import Image as Img import StringIO from django.db.models.signals import post_delete from django.dispatch import receiver Class Mymodel(models.Model): photo= models.ImageField(upload_to="photo/", blank=True, null=True) def save(self, *args, **kwargs): width = 500 height = 500 size = (width,height) isSame = False if self.photo: try: this = Mymodel.objects.get(id=self.id) if this.photo==self.photo : isSame= True except: pass # when new photo then we do nothing, normal case image = Img.open(StringIO.StringIO(self.photo.read())) (imw, imh) = image.size if (imw>width) or (imh>height) : image.thumbnail(size, Img.ANTIALIAS) #If RGBA, convert transparency if image.mode == "RGBA": image.load() background = Img.new("RGB", image.size, (255, 255, 255)) background.paste(image, mask=image.split()[3]) # 3 is the alpha channel image=background output = StringIO.StringIO() image.save(output, format='JPEG', quality=60) output.seek(0) self.photo = InMemoryUploadedFile(output,'ImageField', "%s.jpg" %self.photo.name.split('.')[0], 'image/jpeg', output.len, None) try: this = Mymodel.objects.get(id=self.id) if this.photo==self.photo or isSame : self.photo=this.photo else : this.photo.delete(save=False) except: pass # when new photo then we do nothing, normal case super(Mymodel, self).save(*args, **kwargs) @receiver(post_delete, sender=Mymodel) def photo_post_delete_handler(sender, **kwargs): instance = kwargs['instance'] storage, path = instance.photo.storage, instance.photo.path if (path!='.') and (path!='/') and (path!='photo/') and (path!='photo/.'): storage.delete(path) 

Hope this can help someone;)

+5
source

Try:

 if self.photo.name != '': 

or

 if self.photo.size > 0: 
0
source

Source: https://habr.com/ru/post/971256/


All Articles