template - django-admin command
Django save anula el manejo de ImageField (2)
Después de los problemas que tuve en este hilo , todavía hay un gran problema en mi models.py cuando estoy usando el Administrador de Django. Aquí está mi código (eliminé cosas no relacionadas con mi problema):
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)
Funciona, los archivos se cargan, cambian de tamaño y se convierten a JPEG con éxito cuando sea necesario. El problema, cada vez que lo edito, incluso cuando NO se carga una imagen nueva, crea una nueva imagen (por ejemplo, guardo mi modelo por primera vez con la imagen "hello.jpg", luego lo edito, creará una nueva imagen llamada "hello_1.jpg" incluso si no subí nada). Pensé que el bloque try / except funcionaría solo cuando se editara (por lo que no hay carga de archivos nuevos), pero aparentemente no.
Gracias de antemano por la ayuda :)
Solución final, que funciona para mí:
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)
Espero que pueda ayudar a alguien;)
Tratar:
if self.photo.name != '''':
o
if self.photo.size > 0: