Jugando con Dropbox client en Python

Siempre que tengo un rato libre y me siento inspirado procuro jugar con algo que me divierta de verdad. Me lo paso pipa con Django sobre todo cuando se trata de alguna idea "fuera de lo común".

Esta vez ha sido una mejora para la web de los peques. Teníamos un problema con las fotos, tanto Marta como yo hacemos fotos de forma indiscriminada - a lo paparazzi - de los renacuajos y luego a la hora de subirlas a la web siempre pasa lo mismo:

  • Júntalas todas en un mismo sitio.
  • Procésalas para que el excesivo tamaño de las cámaras de hoy no supongan un problema de ancho de banda.
  • Súbelas a la web en un orden más o menos cronológico.
  • Publícalas.

Las primeras veces lo haces con ilusión, son fotos, son tus hijos... pero a los 2 meses y con más de 800 fotos procesadas es hora de buscar otra solución.

Júntalas todas en un mismo sitio: He pensado en compartir una carpeta Dropbox y dejar que el proceso de selección lo haga cada uno en su móvil. De todas la fotos que hagas sólo subes a Dropbox las que consideres que tienen cierto encanto. Una de las cosas que me encanta de Python es que hay clientes para cualquier API. Otra característica que me chifla de Dropbox es que miman Python (a lo mejor Guido Van Rossum tiene algo que ver). Así que con el cliente oficial para Python he pasado un buen rato de entretenimiento para descargar las fotos de la carpeta compartida.

# Get your app key and secret from the Dropbox developer website
APP_KEY = 'XXXXXX'
APP_SECRET = 'YYYYYY'

# ACCESS_TYPE should be 'dropbox' or 'app_folder' as configured for your app
ACCESS_TYPE = 'app_folder'

# First time
TOKENS = os.path.join(conf.PROJECT_DIR, 'media', 'uploads', 'dropbox', 'dropbox_token.txt')
if not os.path.exists(TOKENS):
    sess = session.DropboxSession(APP_KEY, APP_SECRET, ACCESS_TYPE)
    request_token = sess.obtain_request_token()
    url = sess.build_authorize_url(request_token)

    # Make the user sign in and authorize this token
    print "url:", url
    print "Please visit this website and press the 'Allow' button, then hit 'Enter' here."
    raw_input()

    # This will fail if the user didn't visit the above URL
    access_token = sess.obtain_access_token(request_token)

    token_file = open(TOKENS,'w')
    token_file.write("%s|%s" % (access_token.key,access_token.secret) )
    token_file.close()
else:
    token_file = open(TOKENS)
    token_key,token_secret = token_file.read().split('|')
    token_file.close()
    sess = session.DropboxSession(APP_KEY,APP_SECRET, ACCESS_TYPE )
    sess.set_token(token_key,token_secret)

c = client.DropboxClient(sess)
# Dropbox photo download
f, metadata = c.get_file_and_metadata(cont['path'])
out = open(dropboxdir + '/' + nombre_imagen, 'wb')
out.write(f.read())
out.close()
print "Done!"

Procesado: Una vez descargadas, lo siguiente sería procesar las fotos. El procesado es sencillo, poco más hago que pasar la foto por PIL para reducirla a un tamaño indicado para web y quedarme con unos cuantos datos EXIF que usaré para rotarla y guardar la fecha de captura.

def get_exif(fn):
    """
    data = get_exif('img/2013-04-13 12.17.09.jpg')
    print data
    """
    ret = {}
    i = Image.open(fn)
    info = i._getexif()
    for tag, value in info.items():
        decoded = TAGS.get(tag, tag)
        ret[decoded] = value
    return ret
try:
    # Rotate if needed
    for orientation in ExifTags.TAGS.keys() :
        if ExifTags.TAGS[orientation]=='Orientation' : break
    exif=dict(im2._getexif().items())
    if exif[orientation] == 3 :
        im2=im2.rotate(180, expand=True)
    elif exif[orientation] == 6 :
        im2=im2.rotate(270, expand=True)
    elif exif[orientation] == 8 :
        im2=im2.rotate(90, expand=True)
except:
    pass

im2.thumbnail(size, Image.ANTIALIAS)
if os.path.exists(destdir + '/' + nombre_imagen) == False:
    im2.save(destdir + '/' + nombre_imagen)
    print "Thumbnail done!"

Publicación: Finalmente tan sólo he de guardar el resultado en el destino adecuado y agregar un registro más a la tabla correspondiente de la base de datos. Nada del otro mundo.

# Database
data_image = get_exif(dropboxdir + '/' + nombre_imagen)
capture_data = datetime.strptime(str(data_image['DateTimeOriginal']), "%Y:%m:%d %H:%M:%S")
im = mymodels.Photo(image="uploads/photos/" + nombre_imagen, origen=os.path.basename(cont['path']), insert_date=datetime.now(), capture_date=capture_data, status=True)
im.save()
print "Added to database!"

Teniendo en cuenta que cada día más gente utiliza Dropbox y lo sencillo que parece poder integrarlo directamente con tu web para una simple galería de imágenes, ya se me ocurren un par de casos de uso más. 

django code

About the author

Óscar
has doubledaddy super powers, father of Hugo and Nico, husband of Marta, *nix user, Djangonaut and open source passionate.