Usar Cloud Datastore con Python

En esta página del tutorial de Bookshelf, se explica cómo la aplicación de muestra almacena sus datos persistentes en Google Cloud Datastore. El código de muestra de este paso proporciona ejemplos sobre cómo crear, leer, actualizar y eliminar (CRUD) los datos almacenados en Cloud Datastore.

Esta página forma parte de un tutorial de varias páginas. Para empezar en orden y consultar las instrucciones de configuración, ve a la sección relativa a la aplicación Bookshelf para Python.

Establecer configuración

En esta sección, se usa el código del directorio 2-structured-data. Edita los archivos y ejecuta los comandos de este directorio.

  1. Abre config.py para editarlo.
  2. Utiliza el ID del proyecto, que puede verse en la consola de GCP, como el valor de PROJECT_ID.
  3. Define el valor de DATA_BACKEND como datastore.
  4. Guarda y cierra config.py.
Cloud Datastore es un servicio totalmente administrado que se inicializa y se conecta automáticamente a tu aplicación de App Engine. No se requiere ninguna otra configuración.

Instalar dependencias

Introduce los comandos siguientes para crear un entorno virtual e instalar las dependencias:

Linux/macOS X

virtualenv -p python3 env
source env/bin/activate
pip install -r requirements.txt

Windows

virtualenv -p python3 env
env\scripts\activate
pip install -r requirements.txt

Ejecutar la aplicación en la máquina local

  1. Inicia un servidor web local:

    python main.py
    
  2. Introduce la siguiente dirección en el navegador web:

    http://localhost:8080

Ahora puedes navegar por las páginas web de la aplicación y añadir, editar y eliminar libros.

Presiona Control + C para salir del servidor web local.

Desplegar la aplicación en el entorno flexible de App Engine

  1. Despliega la aplicación de muestra:

    gcloud app deploy
    
  2. Introduce la siguiente dirección en el navegador web. Sustituye [YOUR_PROJECT_ID] por el ID del proyecto:

    https://[YOUR_PROJECT_ID].appspot.com
    

Si actualizas la aplicación, podrás desplegar la versión actualizada con el mismo comando que utilizaste para desplegar la aplicación por primera vez. El nuevo despliegue crea una nueva versión de la aplicación y la establece como la versión predeterminada. No obstante, se conservarán las versiones anteriores, al igual que las instancias de máquina virtual asociadas. Ten en cuenta que todas estas versiones de la aplicación y las instancias de máquina virtual son recursos facturables.

Si eliminas las versiones no predeterminadas de la aplicación, puedes reducir los costes.

Para eliminar una versión de la aplicación, sigue las instrucciones que figuran a continuación:

  1. En GCP Console, dirígete a la página Versiones de App Engine.

    Ir a la página de Versiones

  2. Haz clic en la casilla de verificación junto a la versión de app no predeterminada que deseas borrar.
  3. Haz clic en el botón Borrar en la parte superior de la página para borrar la versión de la app.

Consulta la sección sobre cómo eliminar los recursos facturables en el último paso de este tutorial para obtener más información al respecto.

Estructura de la aplicación

Proceso de despliegue y estructura de la aplicación Bookshelf

La aplicación almacena todos los datos persistentes en Cloud Datastore.

Información sobre el código

En esta sección, se explica detalladamente el código de la aplicación y su funcionamiento.

Gestión de los envíos de formularios que realizan los usuarios

El formulario HTML para añadir o editar permite que los usuarios puedan agregar y editar presentaciones de libros dentro de la aplicación.

Imagen del formulario de añadir/editar

El formulario HTML se crea mediante el uso del motor de plantillas predeterminado de Flask, Jinja2. La siguiente plantilla define un formulario simple que incluye campos de entrada para el título, el autor, la fecha de publicación y la descripción:

{% extends "base.html" %}

{% block content %}
<h3>{{action}} book</h3>

<form method="POST" enctype="multipart/form-data">

  <div class="form-group">
    <label for="title">Title</label>
    <input type="text" name="title" id="title" value="{{book.title}}" class="form-control"/>
  </div>

  <div class="form-group">
    <label for="author">Author</label>
    <input type="text" name="author" id="author" value="{{book.author}}" class="form-control"/>
  </div>

  <div class="form-group">
    <label for="publishedDate">Date Published</label>
    <input type="text" name="publishedDate" id="publishedDate" value="{{book.publishedDate}}" class="form-control"/>
  </div>

  <div class="form-group">
    <label for="description">Description</label>
    <textarea name="description" id="description" class="form-control">{{book.description}}</textarea>
  </div>

  <button type="submit" class="btn btn-success">Save</button>
</form>

{% endblock %}

Gestión de los envíos de formularios

Cuando un usuario hace clic en Add Book (Añadir libro), la vista crud.add muestra el formulario. Cuando el usuario rellena el formulario de Add book (Añadir libro) y hace clic en la opción Save (Guardar), la misma vista gestiona la acción HTTP POST del formulario. Esto inicia el proceso de envío de los datos presentados a Cloud Datastore mediante su transferencia a la función get_model().create.

@crud.route('/add', methods=['GET', 'POST'])
def add():
    if request.method == 'POST':
        data = request.form.to_dict(flat=True)

        book = get_model().create(data)

        return redirect(url_for('.view', id=book['id']))

    return render_template("form.html", action="Add", book={})

El archivo bookshelf/model_datastore.py contiene el código que realiza las funciones CRUD con los datos almacenados en Cloud Datastore. Por ejemplo, la instrucción get_model().create llama a la función create de bookshelf/model_datastore.py. Dicha función envía los datos presentados por el usuario a la función update. Luego, se transfiere un valor null en el primer parámetro, lo cual indica que se trata de un nuevo envío de libros. Aquí presentamos la función update, que se encarga de guardar los datos enviados por el usuario a Cloud Datastore.

def update(data, id=None):
    ds = get_client()
    if id:
        key = ds.key('Book', int(id))
    else:
        key = ds.key('Book')

    entity = datastore.Entity(
        key=key,
        exclude_from_indexes=['description'])

    entity.update(data)
    ds.put(entity)
    return from_datastore(entity)

create = update

La función auxiliar get_client crea un cliente para interactuar con la API de Cloud Datastore.

def get_client():
    return datastore.Client(current_app.config['PROJECT_ID'])

La función auxiliar from_datastore se usa para convertir la clave de entidad del almacén de datos en un ID que la aplicación pueda utilizar.

def from_datastore(entity):
    """Translates Datastore results into the format expected by the
    application.

    Datastore typically returns:
        [Entity{key: (kind, id), prop: val, ...}]

    This returns:
        {id: id, prop: val, ...}
    """
    if not entity:
        return None
    if isinstance(entity, builtin_list):
        entity = entity.pop()

    entity['id'] = entity.key.id
    return entity

Después de que los usuarios hayan añadido libros, puedes hacer clic en el enlace de Books (Libros) para acceder a la página /books, que muestra todos los libros almacenados en Cloud Datastore. La función model_datastore.list se ocupa de mostrar todos los libros a través de los datos recuperados de Cloud Datastore.

def list(limit=10, cursor=None):
    ds = get_client()

    query = ds.query(kind='Book', order=['title'])
    query_iterator = query.fetch(limit=limit, start_cursor=cursor)
    page = next(query_iterator.pages)

    entities = builtin_list(map(from_datastore, page))
    next_cursor = (
        query_iterator.next_page_token.decode('utf-8')
        if query_iterator.next_page_token else None)

    return entities, next_cursor

Este código consulta el almacén de datos a través de datastore.Query, consigue todas las entidades de Book y las devuelve ordenadas por title. También puedes aplicar filtros a las consultas. Echa un vistazo a la documentación de Datastore para obtener más detalles.

Usamos query.fetch para proporcionar a un iterador las peticiones de consulta. Obtenemos los resultados de página en página y devolvemos un cursor para permitir al usuario cargar la página siguiente de resultados.

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...