Consulta a MongoDB desde Flask (parte 2 - paginación)
Posted on mié 28 septiembre 2016 in Tutorial Python • 3 min read
Continuando con la serie de artículos sobre acceso a mongodb desde Flask.
El artículo anterior hace una consulta incial a la base de datos.
Para revisar los artículos relacionados a este artículo pueden ver:
En la base de datos mongodb se tiene lo siguientes datos de los empleados:
[{"edad": 29, "nombre": "Jane Doe", "dni": 8, "sexo": "Femenino", "_id": {"$oid": "57ebbce45fd2bbeffc51330b"}}, {"edad": 39, "nombre": "John Doe", "dni": 7, "sexo": "Masculino", "_id": {"$oid": "57ebbd195fd2bbeffc51330c"}}, {"edad": 55, "nombre": "Pedro Perez", "dni": 6, "sexo": "Masculino", "_id": {"$oid": "57ebbd505fd2bbeffc51330d"}}, {"edad": 65, "nombre": "Petra", "dni": 5, "sexo": "Femenino", "_id": {"$oid": "57ebbd6b5fd2bbeffc51330e"}}, {"edad": 18, "nombre": "Luis Gonzalez", "dni": 4, "sexo": "Masculino", "_id": {"$oid": "57ebc34d5fd2bbeffc51330f"}}, {"edad": 28, "nombre": "Carolina", "dni": 3, "sexo": "Femenino", "_id": {"$oid": "57ebc3715fd2bbeffc513310"}}, {"edad": 34, "nombre": "Luissana", "dni": 2, "sexo": "Femenino", "_id": {"$oid": "57ebc3935fd2bbeffc513311"}}, {"edad": 43, "nombre": "Neg", "dni": 1, "sexo": "Masculino", "_id": {"$oid": "57ebc4b85fd2bbeffc513312"}}]
Ahora se agregó un campo llamado dni, y se tienen 8 empleados.
El código fuente de este artículo lo pueden ver en la rama mongo2 de gitlab.
Estructura de directorios y archivos
tutorial-flask
├── app
│ └── run.py
├── docker-compose.yml
├── Dockerfile
└── README.md
Esta es la misma estructura del artículo anterior.
Archivo Dockerfile y docker-compose.yml
Estos archivos son los mismos del artículo anterior.
Script app/run.py
Este script permite paginar según una variable llamada dni, el cual se usará para realizar la consulta paginada.
A continuación el código de run.py:
#!/usr/bin/env python
#Se importa Flask, reqest y jsonify
from flask import Flask, request,jsonify
#Se importa pyMOngo
from flask_pymongo import PyMongo, pymongo
#Se importa dumps
from bson.json_util import dumps
#Se instancia la clase de Flask, se configura el acceso
#a la base de datos mongodb a empleados
app = Flask(__name__)
app.config['MONGO_DBNAME'] = 'empleados'
app.config['MONGO_URI'] = 'mongodb://mongo:27017/empleados'
#Se asocia la app a pymongo
mongo = PyMongo(app)
#Se define la ruta /dnis con metodo GET
@app.route('/dnis',methods=['GET'])
def dni():
#Se consutla la coleccion empleados
empleados = mongo.db.empleados
#Se toma los argumentos del url offset y limite
offset = int(request.args['offset'])
limite = int(request.args['limite'])
#Se define el decremento como la diferencia entre offset y el limite
decremento = offset-limite
#Se define el incremento como la suma entre offset y limite
incremento = offset+limite
#Mientras no de error de indice
try:
#Se define el dni inicial, el ultimo
dniInicio = empleados.find().sort('dni',pymongo.ASCENDING)
dniUltimo = dniInicio[offset]['dni']
#Se hace la consulta a la base de datos
empleados = empleados.find({'dni': {'$gte': dniUltimo}}).sort('dni',pymongo.ASCENDING).limit(limite)
#Se crea el listado de donde se almacena los diccionarios.
listado = []
#Se agrega a listado os dni y nombres de los empleados.
for i in empleados:
listado.append({'dni': i['dni'],'nombre': i['nombre']})
#Se define el url previo y siguiente, donde se juega con el offset para avanzar o regresar
prev_url = 'http://localhost:5000/dnis?limite=' + str(limite) + '&offset=' + str(decremento)
next_url = 'http://localhost:5000/dnis?limite=' + str(limite) + '&offset=' + str(incremento)
#Si decremento es negativo se coloca el url en blanco.
if ( decremento < 0) :
prev_url = ''
#Se retorna el json con los resultados y los urls.
return jsonify({'resultado': listado,'prev_url':prev_url,'next_url':next_url })
except (IndexError,):
#Si hay error de indice se defin el url siguiente en blanco, el url previo se mantiene.
next_url = ''
prev_url = 'http://localhost:5000/dnis?limite=' + str(limite) + '&offset=' + str(decremento)
#Se retorna un json con el resultado y urls .
return jsonify({'resultado': 'FIN','prev_url':prev_url,'next_url':'' })
if __name__ == "__main__":
#Se corre la aplicacion en modo debug
app.run(host="0.0.0.0",debug=True)
Creación de la imagen docker y ejecución de los contenedores
Para crear la imagen docker se ejecuta:
docker-compose build
Para ejecutar los contenedores:
docker-compose up
A continuación se muestra una imagen de la salida de la ejecución:
A continuación se muestran los documentos por medio de la aplicación robomongo:
Al abrir el url (http://localhost:5000/dnis?limite=3&offset=0 ), donde limite es la cantidad de objetos a mostrar por página, el offset es el desplazamiento.
La primera figura muestra el primer grupo de empleados (no se tiene url para regresar):
Al darle click al siguiente url se tiene a continuación los dni 4,5 y 6 (aparece el url de regresar y avanzar):
Al darle click a avanzar se tienen los empleados de dni 7 y 8:
Como se tienen 8 elementos, se llegó al dni 8, al darle avanzar muestra que se terminó el json y que sólo se tiene enlace para regresar:
¡Haz tu donativo! Si te gustó el artículo puedes realizar un donativo con Bitcoin (BTC) usando la billetera digital de tu preferencia a la siguiente dirección: 17MtNybhdkA9GV3UNS6BTwPcuhjXoPrSzV
O Escaneando el código QR desde la billetera: