variable template ifequal for examples django django-forms image-manipulation

template - inclusion tags django



cambiar el tamaƱo de la imagen al guardar (6)

Debe usar un método para manejar el archivo cargado, como se demuestra en la documentación de Django .

En este método, podría concatenar los fragmentos en una variable (en lugar de escribirlos en el disco directamente), crear una imagen PIL a partir de esa variable, cambiar el tamaño de la imagen y guardarla en el disco.

En PIL, debe mirar Image.fromstring y Image.resize .

¿Cómo puedo cambiar el tamaño de una imagen fácilmente después de que se cargó en Django? Estoy usando Django 1.0.2 y he instalado PIL.

Estaba pensando en anular el método save () del Modelo para cambiar su tamaño, pero realmente no sé cómo comenzar y anularlo.

¿Alguien me puede apuntar en la dirección correcta? Gracias :-)

@ Guðmundur H: Esto no funcionará porque el paquete django-stdimage no funciona en Windows :-(


Recomiendo encarecidamente la aplicación de miniatura Sorl para manejar el cambio de tamaño de imagen de forma fácil y transparente. Va en cada proyecto de Django que empiezo.


Sé que esto es viejo, pero para cualquiera que lo encuentre, hay un paquete, django-thumbs en Django-thumbs: miniaturas fáciles y potentes para Django integradas con StorageBackend , que genera miniaturas automáticamente en los tamaños que especifique, o ninguna si no lo hace t. A continuación, llame a la miniatura que desee con las dimensiones que desee.

Por ejemplo, si desea que una imagen tenga miniaturas de 64x64 y 128x128, simplemente importe thumbs.models.ImageWithThumbsField y thumbs.models.ImageWithThumbsField en lugar de ImageField . Agregue un sizes=((64,64),(128,128)) parámetro sizes=((64,64),(128,128)) a la definición de campo, luego de su plantilla puede llamar:

{{ ClassName.field_name.url_64x64 }}

y

{{ ClassName.field_name.url_128x128 }}

para mostrar las miniaturas Voila! Todo el trabajo se hace en este paquete para usted.


Utilizo este código para manejar las imágenes cargadas, cambiar su tamaño en la memoria (sin guardarlas permanentemente en el disco) y luego guardar el pulgar en un Django ImageField. Hope puede ayudar.

def handle_uploaded_image(i): import StringIO from PIL import Image, ImageOps import os from django.core.files import File # read image from InMemoryUploadedFile image_str = “” for c in i.chunks(): image_str += c # create PIL Image instance imagefile = StringIO.StringIO(image_str) image = Image.open(imagefile) # if not RGB, convert if image.mode not in (“L”, “RGB”): image = image.convert(“RGB”) #define file output dimensions (ex 60x60) x = 130 y = 130 #get orginal image ratio img_ratio = float(image.size[0]) / image.size[1] # resize but constrain proportions? if x==0.0: x = y * img_ratio elif y==0.0: y = x / img_ratio # output file ratio resize_ratio = float(x) / y x = int(x); y = int(y) # get output with and height to do the first crop if(img_ratio > resize_ratio): output_width = x * image.size[1] / y output_height = image.size[1] originX = image.size[0] / 2 - output_width / 2 originY = 0 else: output_width = image.size[0] output_height = y * image.size[0] / x originX = 0 originY = image.size[1] / 2 - output_height / 2 #crop cropBox = (originX, originY, originX + output_width, originY + output_height) image = image.crop(cropBox) # resize (doing a thumb) image.thumbnail([x, y], Image.ANTIALIAS) # re-initialize imageFile and set a hash (unique filename) imagefile = StringIO.StringIO() filename = hashlib.md5(imagefile.getvalue()).hexdigest()+’.jpg’ #save to disk imagefile = open(os.path.join(‘/tmp’,filename), ‘w’) image.save(imagefile,’JPEG’, quality=90) imagefile = open(os.path.join(‘/tmp’,filename), ‘r’) content = File(imagefile) return (filename, content) #views.py form = YourModelForm(request.POST, request.FILES, instance=profile) if form.is_valid(): ob = form.save(commit=False) try: t = handle_uploaded_image(request.FILES[‘icon’]) ob.image.save(t[0],t[1]) except KeyError: ob.save()


Recomiendo usar StdImageField desde django-stdimage , debería manejar todo el trabajo sucio para usted. Es fácil de usar, solo especifica las dimensiones de la imagen redimensionada en la definición de campo:

class MyModel(models.Model): image = StdImageField(upload_to=''path/to/img'', size=(640, 480))

Mira los documentos, también puede hacer miniaturas.


Aquí hay una solución completa para ti usando un formulario. Utilicé vistas de administrador para esto:

class MyInventoryItemForm(forms.ModelForm): class Meta: model = InventoryItem exclude = [''thumbnail'', ''price'', ''active''] def clean_photo(self): import StringIO image_field = self.cleaned_data[''photo''] photo_new = StringIO.StringIO(image_field.read()) try: from PIL import Image, ImageOps except ImportError: import Image import ImageOps image = Image.open(photo_new) # ImageOps compatible mode if image.mode not in ("L", "RGB"): image = image.convert("RGB") image.thumbnail((200, 200), Image.ANTIALIAS) image_file = StringIO.StringIO() image.save(image_file, ''png'') image_field.file = image_file return image_field

Mi modelo de inventario se ve así:

class InventoryItem(models.Model): class Meta: ordering = [''name''] verbose_name_plural = "Items" def get_absolute_url(self): return "/products/{0}/".format(self.slug) def get_file_path(instance, filename): if InventoryItem.objects.filter(pk=instance.pk): cur_inventory = InventoryItem.objects.get(pk=instance.pk) if cur_inventory.photo: old_filename = str(cur_inventory.photo) os.remove(os.path.join(MEDIA_ROOT, old_filename)) ext = filename.split(''.'')[-1] filename = "{0}.{1}".format(uuid.uuid4(), ext) return os.path.join(''inventory'', filename) #return os.path.join(filename) def admin_image(self): return ''<img height="50px" src="{0}/{1}"/>''.format(MEDIA_URL, self.photo) admin_image.allow_tags = True photo = models.ImageField(_(''Image''), upload_to=get_file_path, storage=fs, blank=False, null=False) thumbnail = models.ImageField(_(''Thumbnail''), upload_to="thumbnails/", storage=fs, blank=True, null=True)

....

Terminé sobreescribiendo la función de guardar del modelo para guardar la foto y un pulgar en lugar de simplemente cambiar el tamaño de la foto:

def save(self): # Save this photo instance first super(InventoryItem, self).save() from PIL import Image from cStringIO import StringIO from django.core.files.uploadedfile import SimpleUploadedFile # Set our max thumbnail size in a tuple (max width, max height) THUMBNAIL_SIZE = (200, 200) # Open original photo which we want to thumbnail using PIL''s Image object image = Image.open(os.path.join(MEDIA_ROOT, self.photo.name)) if image.mode not in (''L'', ''RGB''): image = image.convert(''RGB'') image.thumbnail(THUMBNAIL_SIZE, Image.ANTIALIAS) # Save the thumbnail temp_handle = StringIO() image.save(temp_handle, ''png'') # image stored to stringIO temp_handle.seek(0) # sets position of file to 0 # Save to the thumbnail field suf = SimpleUploadedFile(os.path.split(self.photo.name)[-1], temp_handle.read(), content_type=''image/png'') # reads in the file to save it self.thumbnail.save(suf.name+''.png'', suf, save=False) #Save this photo instance again to save the thumbnail super(InventoryItem, self).save()

Ambos funcionan bien, dependiendo de lo que quieras hacer :)