Saltar al contenido

¿Cómo se convierte una `Imagen` de PIL en un` Archivo` de Django?

Solución:

La forma de hacer esto sin tener que volver a escribir en el sistema de archivos, y luego traer el archivo a la memoria a través de una llamada abierta, es hacer uso de StringIO y Django InMemoryUploadedFile. Aquí hay una muestra rápida de cómo puede hacer esto. Esto supone que ya tiene una imagen en miniatura llamada ‘pulgar’:

import StringIO

from django.core.files.uploadedfile import InMemoryUploadedFile

# Create a file-like object to write thumb data (thumb data previously created
# using PIL, and stored in variable 'thumb')
thumb_io = StringIO.StringIO()
thumb.save(thumb_io, format="JPEG")

# Create a new Django file-like object to be used in models as ImageField using
# InMemoryUploadedFile.  If you look at the source in Django, a
# SimpleUploadedFile is essentially instantiated similarly to what is shown here
thumb_file = InMemoryUploadedFile(thumb_io, None, 'foo.jpg', 'image/jpeg',
                                  thumb_io.len, None)

# Once you have a Django file-like object, you may assign it to your ImageField
# and save.
...

Avísame si necesitas más aclaraciones. Tengo esto funcionando en mi proyecto en este momento, subiendo a S3 usando django-storages. Me tomó la mayor parte del día encontrar la solución aquí.

Tuve que hacer esto en unos pocos pasos, imagejpeg () en php requiere un proceso similar. Por no decir que no hay forma de guardar cosas en la memoria, pero este método le da una referencia de archivo tanto a la imagen original como al pulgar (generalmente es una buena idea en caso de que tenga que volver atrás y cambiar el tamaño del pulgar).

  1. guarda el archivo
  2. ábralo desde el sistema de archivos con PIL,
  3. guardar en un directorio temporal con PIL,
  4. luego ábralo como un archivo Django para que esto funcione.

Modelo:

class YourModel(Model):
    img = models.ImageField(upload_to='photos')
    thumb = models.ImageField(upload_to='thumbs')

Uso:

#in upload code
uploaded = request.FILES['photo']
from django.core.files.base import ContentFile
file_content = ContentFile(uploaded.read())
new_file = YourModel() 
#1 - get it into the DB and file system so we know the real path
new_file.img.save(str(new_file.id) + '.jpg', file_content)
new_file.save()

from PIL import Image
import os.path

#2, open it from the location django stuck it
thumb = Image.open(new_file.img.path)
thumb.thumbnail(100, 100)

#make tmp filename based on id of the model
filename = str(new_file.id)

#3. save the thumbnail to a temp dir

temp_image = open(os.path.join('/tmp',filename), 'w')
thumb.save(temp_image, 'JPEG')

#4. read the temp file back into a File
from django.core.files import File
thumb_data = open(os.path.join('/tmp',filename), 'r')
thumb_file = File(thumb_data)

new_file.thumb.save(str(new_file.id) + '.jpg', thumb_file)

Este es un ejemplo de trabajo real para pitón 3.5 y django 1.10

en views.py:

from io import BytesIO
from django.core.files.base import ContentFile
from django.core.files.uploadedfile import InMemoryUploadedFile

def pill(image_io):
    im = Image.open(image_io)
    ltrb_border = (0, 0, 0, 10)
    im_with_border = ImageOps.expand(im, border=ltrb_border, fill="white")

    buffer = BytesIO()
    im_with_border.save(fp=buffer, format="JPEG")
    buff_val = buffer.getvalue()
    return ContentFile(buff_val)

def save_img(request)
    if request.POST:
       new_record = AddNewRecordForm(request.POST, request.FILES)
       pillow_image = pill(request.FILES['image'])
       image_file = InMemoryUploadedFile(pillow_image, None, 'foo.jpg', 'image/jpeg', pillow_image.tell, None)
       request.FILES['image'] = image_file  # really need rewrite img in POST for success form validation
       new_record.image = request.FILES['image']
       new_record.save()
       return redirect(...)
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *