Google App Engine es un entorno en el que crear aplicaciones en la nube que nos permite desarrollo en Python + Django. Dado que es almacenamiento en nube, no podemos usar el disco duro para almacenar ficheros de usuario.
Google App Engine nos proporciona una API para almacenar BLOBs (Blobstore Python API), pero ¿cómo usarla en un proyecto DJango? no es algo inmediato, pero en esta entrada de blog veremos cómo hacerlo paso a paso.
En el manual oficial de Blobstore Python API, explican muy detalladamente como utilizar este mecanismo en un script Python (se recomienda leer esa documentación para captar todos los detalles: Ver documentación oficial), pero cuando pretendemos usarlo en un modelo DJango, la implantación no es tan simple, por la falta de documentación oficial, y porqué no decirlo, extraoficial.
Tras mucho ensayo error, hemos conseguido implantarlo perfectamente, así que lo compartimos con todos los lectores para que cuando lo necesiten, la experiencia sea todo un éxito :)
Partiremos de la base de que necesitamos un formulario mediante el que subir el fichero, por ejemplo el siguiente:
<form action="{{url}}" method="POST" enctype="multipart/form-data">
<input type="file" name="file"><br/>
<input type="submit" name="submit" value="Submit">
</form>
Ya podemos apreciar que necesitamos una URL de subida, la API de Blobstore nos da una funcionalidad para conseguir esa URL:
blobstore.create_upload_url(callback)
callback es una URL de nuestro sistema que se ejecutará cuando se haya subido el fichero y se haya almacenado en la nube de Google. La API de Blobstore modificará algunas cosas en la llamada a nuestro callback para que podamos trabajar con el fichero ya subido. De esta forma Google se encarga de almacenar el fichero y nos da una referencia que podemos usar para almacenar en nuestra base de datos y así tener localizado a ese fichero.
De esta forma, si nuestra URL para relacionar el fichero fuese "/subida_fichero", entonces tendríamos los siguientes ingredientes en nuestra receta:
En este momento ya tendríamos el flujo creado, y nuestro método subida_fichero se está ejecutando una vez el fichero está en la nube. ahora toca poder acceder a la referencia de ese fichero para poder guardarla. Para ello, Google App Engine modifica el objeto request.FILES['file'], y le añade un componente más, llamado blobstore_info, de esta forma, podemos acceder a toda la meta-información del fichero subido mediante request.FILES['file'].blobstore_info.
Dentro de esa meta-información hay varios datos, pero quizá el más relevante será la KEY del fichero, ya que será el elemento que nos permita usar la API para iniciar una descarga hacia el usuario del mismo. De esta forma, el dato que habría que almacenar en nuestra base de datos, sería la cadena de texto que representa a esa KEY y eso se haría de forma completa mediante la siguiente línea:
request.FILES['file'].blobstore_info.key().__str__()
Con toda esta información, ya habríamos almacenado el fichero en la nube, y tendríamos la KEY almacenada en nuestra Base de Datos.
¿Cómo hacemos la descarga hacia el usuario?
Debemos crear un método en views.py y declararlo en urls.py para que el usuario pueda acceder a él, y ya dentro de ese método, debemos conseguir la clave del fichero, es decir, la KEY, que teníamos almacenada en nuestra Base de Datos. Supongamos que ya tenemos esa clave en la variable key.
Podemos obtener toda la meta-información de ese fichero mediante la sentencia: blob_info = blobstore.BlobInfo.get(resource)
Con ese objeto, ya podemos acceder al contenido y enviárselo al usuario, usando para ello el siguiente código dentro de nuestro método de views.py:
response = HttpResponse(blob_info.open().read(), content_type=blob_info.content_type)
response['Content-Disposition'] = 'attachment; filename="'+blob_info.filename+'"'
return response
Esperamos que os haya sido de utilidad, ¿Alguna vez habías intentado hacerlo?
José Carlos Calvo Tudela
Google App Engine nos proporciona una API para almacenar BLOBs (Blobstore Python API), pero ¿cómo usarla en un proyecto DJango? no es algo inmediato, pero en esta entrada de blog veremos cómo hacerlo paso a paso.
En el manual oficial de Blobstore Python API, explican muy detalladamente como utilizar este mecanismo en un script Python (se recomienda leer esa documentación para captar todos los detalles: Ver documentación oficial), pero cuando pretendemos usarlo en un modelo DJango, la implantación no es tan simple, por la falta de documentación oficial, y porqué no decirlo, extraoficial.
Tras mucho ensayo error, hemos conseguido implantarlo perfectamente, así que lo compartimos con todos los lectores para que cuando lo necesiten, la experiencia sea todo un éxito :)
Partiremos de la base de que necesitamos un formulario mediante el que subir el fichero, por ejemplo el siguiente:
<form action="{{url}}" method="POST" enctype="multipart/form-data">
<input type="file" name="file"><br/>
<input type="submit" name="submit" value="Submit">
</form>
Ya podemos apreciar que necesitamos una URL de subida, la API de Blobstore nos da una funcionalidad para conseguir esa URL:
blobstore.create_upload_url(callback)
callback es una URL de nuestro sistema que se ejecutará cuando se haya subido el fichero y se haya almacenado en la nube de Google. La API de Blobstore modificará algunas cosas en la llamada a nuestro callback para que podamos trabajar con el fichero ya subido. De esta forma Google se encarga de almacenar el fichero y nos da una referencia que podemos usar para almacenar en nuestra base de datos y así tener localizado a ese fichero.
De esta forma, si nuestra URL para relacionar el fichero fuese "/subida_fichero", entonces tendríamos los siguientes ingredientes en nuestra receta:
- Para generar la variable url, usaríamos la siguiente llamada a la API de Blobstore
blobstore.create_upload_url("/subida_fichero") - Por tanto, en el fichero urls.py debemos crear una línea de URL similar a la siguiente
url(r'^subida_fichero$', "subida_fichero", name="subida_fichero") - Y por último en el fichero views.py debemos tener el siguiente método:
def subida_fichero(request):
En este momento ya tendríamos el flujo creado, y nuestro método subida_fichero se está ejecutando una vez el fichero está en la nube. ahora toca poder acceder a la referencia de ese fichero para poder guardarla. Para ello, Google App Engine modifica el objeto request.FILES['file'], y le añade un componente más, llamado blobstore_info, de esta forma, podemos acceder a toda la meta-información del fichero subido mediante request.FILES['file'].blobstore_info.
Dentro de esa meta-información hay varios datos, pero quizá el más relevante será la KEY del fichero, ya que será el elemento que nos permita usar la API para iniciar una descarga hacia el usuario del mismo. De esta forma, el dato que habría que almacenar en nuestra base de datos, sería la cadena de texto que representa a esa KEY y eso se haría de forma completa mediante la siguiente línea:
request.FILES['file'].blobstore_info.key().__str__()
Con toda esta información, ya habríamos almacenado el fichero en la nube, y tendríamos la KEY almacenada en nuestra Base de Datos.
¿Cómo hacemos la descarga hacia el usuario?
Debemos crear un método en views.py y declararlo en urls.py para que el usuario pueda acceder a él, y ya dentro de ese método, debemos conseguir la clave del fichero, es decir, la KEY, que teníamos almacenada en nuestra Base de Datos. Supongamos que ya tenemos esa clave en la variable key.
Podemos obtener toda la meta-información de ese fichero mediante la sentencia: blob_info = blobstore.BlobInfo.get(resource)
Con ese objeto, ya podemos acceder al contenido y enviárselo al usuario, usando para ello el siguiente código dentro de nuestro método de views.py:
response = HttpResponse(blob_info.open().read(), content_type=blob_info.content_type)
response['Content-Disposition'] = 'attachment; filename="'+blob_info.filename+'"'
return response
Esperamos que os haya sido de utilidad, ¿Alguna vez habías intentado hacerlo?
José Carlos Calvo Tudela
Hola, trate de aplicar esto, pero realmente no pude, te agradecería algun ejemplo con este código, pues yo recien empecé con Django non rel sobre AppEngine y no he podido mostrar imagenes que el usuario sube, como por ejemplo su foto de perfil. Me ayudarias mucho en mi trabajo si tienes algun ejemplo completo que funcione.
ResponderEliminarSaludos y atento a tu respuesta
Buenos días!
EliminarQuizá este trozo de código te sea de utilidad: http://pastie.org/9525997
no logro hacer funcionar lo de subir "x" archivo desde el administrador de django en en appengine y en mi mysql local, cualquier otro dato es bien aceptado por la db pudieras, pasarme las configuraciones básicas para lograrlo el model.py form.py views.py urls.py ... te lo agradeceria montones
Eliminar