Django Guardar imágenes (o blobs) desde la red

Debido a las consultas amplío el post anterior para aclarar un poco el proceso suponiendo que bajamos las imágenes desde un servidor sFTP, sólo hay que cambiar los parámetros de pycurl para operar con http, https, etc...

Primero bajamos la imagen a memoria con algún gestor (pycurl por ejemplo o urllib) y guardarlo en un cStringIO:


import pycurl, cStringIO

buf = cStringIO.StringIO()
url=('ftps://%s:990/%s' % (ip, fichero))
privatekey = '/home/sss/.ssh/id_rsa'
options = {
pycurl.USERPWD: 'xxxxx:xxxx',
pycurl.SSLKEYPASSWD: 'adfasdfasdfas',
pycurl.SSH_PRIVATE_KEYFILE: privatekey,
pycurl.SSH_PUBLIC_KEYFILE: privatekey + '.pub',
#pycurl.WRITEDATA: open('/dev/null', 'wb'),
pycurl.VERBOSE: 1,
pycurl.URL: url,
pycurl.HEADER: 1,
pycurl.NOBODY: 1,
pycurl.WRITEFUNCTION: buf.write,
pycurl.NOPROGRESS: 1,
pycurl.SSL_VERIFYPEER: 0,
pycurl.SSL_VERIFYHOST: 0,
}

gestor = pycurl.Curl()
try:
for (k, v) in options.items():
print k, v
gestor.setopt(k, v)
except Exception, msg:
logging.info('Error setopt %s' % msg)

gestor.perform()



Ahora ya tenemos la imagen en memoria (buf), vamos a grabarla (django la graba en disco y en la db solo se guarda el path), el único problema es que ImageField espera un campo file, pero lo solucionaremos con un workaround:

En tu modelo pones:

class Persona(models.Model):
.....
imagen=models.ImageField(upload_to=settings.PATH_FOTOS_CLIENTES, blank=True)


Donde settings.PATH_FOTOS_CLIENTES apunta a la ruta que cuelga de la ruta que tengas en settings.MEDIA_ROOT y tiene el formato siguiente o similar (en settings.py):


PATH_FOTOS_CLIENTES='clientes/%Y/%m/%d'


Ahora tenemos que pasar de la imagen que tienes cargada en memoria a un stream tipo 'file' para que pueda ser guardado por el modelo:


from django.core.files.uploadedfile import SimpleUploadedFile

foto = SimpleUploadedFile('imagencliente.jpg',
buf.getvalue(),
"image/jpeg")


y ya salvamos:

p=Persona( imagen=foto )
p.save()


Comentad si os surge alguna duda.
Saludos,
Pere Vilás.

Consultas en Django

Unos pequeños apuntes cogidos al vuelo de consultas en django

Django Guardar imágenes desde string

Para guardar una imagen en un campo de tipo ImageField de Model desde una cadena como un POST http o desde memoria hacemos lo siguiente:


from django.core.files.uploadedfile import SimpleUploadedFile
import cStringIO

buf = cStringIO.StringIO()
# adquirimos imagen y la guardamos en buf i.e. mediante pycurl

foto = SimpleUploadedFile('imagen.jpg', buf.getvalue(), "image/jpeg")

# ahora foto contiene el stream pero en formato 'fichero'

p=Modelo( imagen=foto )
p.save()



Espero que os sirva ;-)

Django Evitar error en el administrador "decoding Unicode is not supported"

Si, como es probable, os habéis encontrado con este error en el administrador cuando examináis modelos con caracteres utf-8, creo que puede deberse al hecho de que django sirve los strings en unicode pero sin codificar.

En python, en el momento que intentamos algo como esto:

>>> unicode('pepe', 'utf-8')
u'pepe'
>>> unicode(u'pepe', 'utf-8')

Traceback (most recent call last):
File "", line 1, in
TypeError: decoding Unicode is not supported

Obtenemos el TypeError. En el admin de django, el error lo obtendremos siempre que grabemos caracteres >255. Parece provenir del hecho de codificar el unicode en ascii en vez de utf-8 ¿?.

Si hacemos:

def __unicode__(self):
return unicode(self.descripcion)


Obtendremos el error de decodificación ascii, pero si hacemos...


def __unicode__(self):
return unicode(self.descripcion, 'utf-8')


...nos funcionará pero no podremos usar el admin para examinar el modelo porque nos genera el error anterior.

Tenemos dos posibilidades, aunque no las comprendo en profundidad:

Solución 1):

from django.utils.encoding import smart_unicode

En los modelos poner:

def __unicode__(self):
return smart_unicode(("%s" % self.descripcion))


Solución 2) Llamado "método del literal"

def __unicode__(self):
return (u"%s" % self.descripcion)


En todo caso es conveniente poner el setting

DEFAULT_CHARSET='utf-8'

que fuerza utf-8 a la hora de procesar y servir las plantillas.

Más info sobre este tema estaría bien. En mi caso uso mysql con utf-8 y ordenación spanish2, ubuntu 10.10 con utf-8 y apache forzado a servir utf-8.