El autor seleccionó el Fondo de Software Libre y de Código Abierto para recibir una donación como parte del programa Escribe para Donaciones.
Introducción
Flask es un marco de trabajo web ligero para Python que proporciona herramientas y características útiles para crear aplicaciones web en el lenguaje Python. SQLAlchemy es un kit de herramientas SQL que proporciona acceso eficiente y de alto rendimiento a bases de datos relacionales. Proporciona formas de interactuar con varios motores de base de datos como SQLite, MySQL y PostgreSQL. Te da acceso a las funcionalidades SQL de la base de datos. Y también te proporciona un Mapeador Relacional de Objetos (ORM), que te permite hacer consultas y manejar datos usando objetos y métodos simples de Python. Flask-SQLAlchemy es una extensión de Flask que facilita el uso de SQLAlchemy con Flask, proporcionándote herramientas y métodos para interactuar con tu base de datos en tus aplicaciones Flask a través de SQLAlchemy.
En este tutorial, utilizarás Flask y Flask-SQLAlchemy para crear un sistema de gestión de empleados con una base de datos que tenga una tabla para los empleados. Cada empleado tendrá un ID único, un nombre, un apellido, un correo electrónico único, un valor entero para su edad, una fecha para el día en que se unieron a la empresa, y un valor booleano para determinar si un empleado está actualmente activo o fuera de la oficina.
Utilizarás el shell de Flask para consultar una tabla y obtener registros de la tabla basados en un valor de columna (por ejemplo, un correo electrónico). Obtendrás registros de empleados en ciertas condiciones, como obtener solo empleados activos o obtener una lista de empleados fuera de la oficina. Ordenarás los resultados por un valor de columna y contarás y limitarás los resultados de la consulta. Finalmente, utilizarás la paginación para mostrar un cierto número de empleados por página en una aplicación web.
Prerrequisitos
-
Un entorno de programación Python 3 local. Sigue el tutorial para tu distribución en la serie Cómo instalar y configurar un entorno de programación local para Python 3. En este tutorial llamaremos a nuestro directorio de proyecto
flask_app
. -
Un entendimiento de los conceptos básicos de Flask, como rutas, funciones de vista y plantillas. Si no estás familiarizado con Flask, consulta Cómo Crear Tu Primera Aplicación Web Usando Flask y Python y Cómo Usar Plantillas en una Aplicación Flask.
-
Un entendimiento de los conceptos básicos de HTML. Puedes revisar nuestra serie de tutoriales Cómo Construir un Sitio Web con HTML para conocimientos previos.
-
Un entendimiento de los conceptos básicos de Flask-SQLAlchemy, como configurar una base de datos, crear modelos de base de datos e insertar datos en la base de datos. Consulta Cómo usar Flask-SQLAlchemy para interactuar con bases de datos en una aplicación Flask para conocimientos previos.
Paso 1 — Configuración de la Base de Datos y el Modelo
En este paso, instalarás los paquetes necesarios y configurarás tu aplicación Flask, la base de datos Flask-SQLAlchemy y el modelo de empleado que representa la tabla employee
donde almacenarás tus datos de empleado. Insertarás algunos empleados en la tabla employee
y agregarás una ruta y una página donde se mostrarán todos los empleados en la página de índice de tu aplicación.
Primero, con tu entorno virtual activado, instala Flask y Flask-SQLAlchemy:
Una vez que la instalación esté completa, recibirás una salida con la siguiente línea al final:
Output
Successfully installed Flask-2.1.2 Flask-SQLAlchemy-2.5.1 Jinja2-3.1.2 MarkupSafe-2.1.1 SQLAlchemy-1.4.37 Werkzeug-2.1.2 click-8.1.3 greenlet-1.1.2 itsdangerous-2.1.2
Con los paquetes requeridos instalados, abre un nuevo archivo llamado app.py
en tu directorio flask_app
. Este archivo contendrá código para configurar la base de datos y tus rutas de Flask:
Agrega el siguiente código a app.py
. Este código configurará una base de datos SQLite y un modelo de base de datos de empleados representando la tabla employee
que usarás para almacenar los datos de tus empleados:
Guarda y cierra el archivo.
Aquí, importas el módulo os
, que te brinda acceso a interfaces del sistema operativo diversas. Lo usarás para construir una ruta de archivo para tu archivo de base de datos database.db
.
Del paquete flask
, importas los ayudantes que necesitas para tu aplicación: la clase Flask
para crear una instancia de aplicación Flask, render_template()
para renderizar plantillas, el objeto request
para manejar solicitudes, url_for()
para construir URLs y la función redirect()
para redirigir usuarios. Para obtener más información sobre rutas y plantillas, consulta Cómo Usar Plantillas en una Aplicación Flask.
Luego, importas la clase SQLAlchemy
de la extensión Flask-SQLAlchemy, que te brinda acceso a todas las funciones y clases de SQLAlchemy, además de ayudantes y funcionalidades que integran Flask con SQLAlchemy. Lo usarás para crear un objeto de base de datos que se conecta a tu aplicación Flask.
Para construir una ruta para tu archivo de base de datos, defines un directorio base como el directorio actual. Utilizas la función os.path.abspath()
para obtener la ruta absoluta del directorio del archivo actual. La variable especial __file__
contiene la ruta del archivo app.py
actual. Almacenas la ruta absoluta del directorio base en una variable llamada basedir
.
Luego creas una instancia de la aplicación Flask llamada app
, que utilizas para configurar dos claves de configuración de Flask-SQLAlchemy:
-
SQLALCHEMY_DATABASE_URI
: La URI de la base de datos para especificar la conexión que deseas establecer. En este caso, la URI sigue el formatosqlite:///ruta/a/database.db
. Utilizas la funciónos.path.join()
para unir inteligentemente el directorio base que construiste y almacenaste en la variablebasedir
con el nombre del archivodatabase.db
. Esto se conectará a un archivo de base de datosdatabase.db
en tu directorioflask_app
. El archivo se creará una vez que inicies la base de datos. -
SQLALCHEMY_TRACK_MODIFICATIONS
: Una configuración para habilitar o deshabilitar el seguimiento de modificaciones de objetos. Lo configuras enFalse
para deshabilitar el seguimiento, lo que utiliza menos memoria. Para más información, consulta la página de configuración en la documentación de Flask-SQLAlchemy.
Después de configurar SQLAlchemy estableciendo una URI de base de datos y deshabilitando el seguimiento, creas un objeto de base de datos utilizando la clase SQLAlchemy
, pasando la instancia de la aplicación para conectar tu aplicación Flask con SQLAlchemy. Almacenas tu objeto de base de datos en una variable llamada db
, que utilizarás para interactuar con tu base de datos.
Después de configurar la instancia de la aplicación y el objeto de base de datos, heredas de la clase db.Model
para crear un modelo de base de datos llamado Empleado
. Este modelo representa la tabla empleado
, y tiene las siguientes columnas:
id
: El ID del empleado, una clave primaria entera.firstname
: El nombre del empleado, una cadena con una longitud máxima de 100 caracteres.nullable=False
significa que esta columna no debe estar vacía.lastname
: El apellido del empleado, una cadena con una longitud máxima de 100 caracteres.nullable=False
significa que esta columna no debe estar vacía.email
: El correo electrónico del empleado, una cadena con una longitud máxima de 100 caracteres.unique=True
significa que cada correo electrónico debe ser único.nullable=False
significa que su valor no debe estar vacío.age
: La edad del empleado, un valor entero.hire_date
: La fecha en que el empleado fue contratado. Se establecedb.Date
como el tipo de columna para declararlo como una columna que contiene fechas.active
: Una columna que contendrá un valor booleano para indicar si el empleado está actualmente activo o fuera de la oficina.
La función especial __repr__
te permite dar a cada objeto una representación de cadena para reconocerlo con fines de depuración. En este caso, utilizas el nombre y apellido del empleado para representar cada objeto de empleado.
Ahora que has establecido la conexión a la base de datos y el modelo de empleado, escribirás un programa en Python para crear tu base de datos y la tabla de employee
y poblar la tabla con algunos datos de empleados.
Abre un archivo nuevo llamado init_db.py
en tu directorio flask_app
:
Agrega el siguiente código para eliminar las tablas de base de datos existentes y comenzar desde una base de datos limpia, crear la tabla de employee
, e insertar nueve empleados en ella:
Aquí, importas la clase date()
del módulo datetime
para usarla para establecer las fechas de contratación de los empleados.
Importas el objeto de la base de datos y el modelo Employee
. Llamas a la función db.drop_all()
para eliminar todas las tablas existentes y evitar la posibilidad de que exista una tabla de employee
ya poblada en la base de datos, lo que podría causar problemas. Esto elimina todos los datos de la base de datos cada vez que ejecutas el programa init_db.py
. Para obtener más información sobre cómo crear, modificar y eliminar tablas de base de datos, consulta Cómo usar Flask-SQLAlchemy para interactuar con bases de datos en una aplicación Flask.
Luego creas varias instancias del modelo Employee
, que representan a los empleados que consultarás en este tutorial, y los agregas a la sesión de la base de datos usando la función db.session.add_all()
. Por último, confirmas la transacción y aplicas los cambios a la base de datos usando db.session.commit()
.
Guarda y cierra el archivo.
Ejecuta el programa init_db.py
:
Para echar un vistazo a los datos que has agregado a tu base de datos, asegúrate de que tu entorno virtual esté activado y abre la terminal de Flask para consultar todos los empleados y mostrar sus datos:
Ejecuta el siguiente código para consultar todos los empleados y mostrar sus datos:
Utilizas el método all()
del atributo query
para obtener todos los empleados. Iteras a través de los resultados y muestras la información del empleado. Para la columna active
, utilizas una declaración condicional para mostrar el estado actual del empleado, ya sea 'Activo'
o 'Fuera de la oficina'
.
Recibirás la siguiente salida:
OutputJohn Doe
Email: [email protected]
Age: 32
Hired: 2012-03-03
Active
----
Mary Doe
Email: [email protected]
Age: 38
Hired: 2016-06-07
Active
----
Jane Tanaka
Email: [email protected]
Age: 32
Hired: 2015-09-12
Out of Office
----
Alex Brown
Email: [email protected]
Age: 29
Hired: 2019-01-03
Active
----
James White
Email: [email protected]
Age: 24
Hired: 2021-02-04
Active
----
Harold Ishida
Email: [email protected]
Age: 52
Hired: 2002-03-06
Out of Office
----
Scarlett Winter
Email: [email protected]
Age: 22
Hired: 2021-04-07
Active
----
Emily Vill
Email: [email protected]
Age: 27
Hired: 2019-06-09
Active
----
Mary Park
Email: [email protected]
Age: 30
Hired: 2021-08-11
Active
----
Puedes ver que todos los empleados que hemos agregado a la base de datos se muestran correctamente.
Sal del terminal de Flask:
A continuación, crearás una ruta Flask para mostrar a los empleados. Abre app.py
para editarlo:
Agrega la siguiente ruta al final del archivo:
Guarda y cierra el archivo.
Esto consulta a todos los empleados, renderiza una plantilla index.html
y le pasa los empleados que obtienes.
Cree un directorio de plantillas y una plantilla base:
Agregue lo siguiente a base.html
:
Guarde y cierre el archivo.
Aquí, se utiliza un bloque de título y se agrega algo de estilo CSS. Se añade una barra de navegación con dos elementos, uno para la página de índice y otro para una página de Acerca de inactiva. Esta barra de navegación se reutilizará en toda la aplicación en las plantillas que hereden de esta plantilla base. El bloque de contenido se reemplazará con el contenido de cada página. Para más información sobre plantillas, consulta Cómo Usar Plantillas en una Aplicación Flask.
A continuación, abre una nueva plantilla index.html
que renderizaste en app.py
:
Agrega el siguiente código al archivo:
Aquí, recorres los empleados y muestras la información de cada empleado. Si el empleado está activo, añades una etiqueta (Activo), de lo contrario, muestras una etiqueta (Fuera de la Oficina).
Guarda y cierra el archivo.
Mientras estés en el directorio flask_app
con tu entorno virtual activado, dile a Flask acerca de la aplicación (app.py
en este caso) utilizando la variable de entorno FLASK_APP
. Luego, establece la variable de entorno FLASK_ENV
en development
para ejecutar la aplicación en modo de desarrollo y obtener acceso al depurador. Para obtener más información sobre el depurador de Flask, consulta Cómo Manejar Errores en una Aplicación Flask. Utiliza los siguientes comandos para hacer esto:
Luego, ejecuta la aplicación:
Con el servidor de desarrollo en funcionamiento, visita la siguiente URL usando tu navegador:
http://127.0.0.1:5000/
Verás los empleados que has agregado a la base de datos en una página similar a la siguiente:
Deja el servidor en ejecución, abre otra terminal y continúa con el siguiente paso.
Has mostrado los empleados que tienes en tu base de datos en la página de índice. A continuación, usarás la consola de Flask para consultar empleados usando diferentes métodos.
Paso 2 — Consulta de Registros
En este paso, utilizarás la consola de Flask para consultar registros, y filtrar y recuperar resultados utilizando múltiples métodos y condiciones.
Con tu entorno de programación activado, establece las variables FLASK_APP
y FLASK_ENV
, y abre la consola de Flask:
Importa el objeto db
y el modelo Employee
:
Recuperando Todos los Registros
Como has visto en el paso anterior, puedes usar el método all()
en el atributo query
para obtener todos los registros de una tabla:
La salida será una lista de objetos que representan a todos los empleados:
Output
[<Employee John Doe>, <Employee Mary Doe>, <Employee Jane Tanaka>, <Employee Alex Brown>, <Employee James White>, <Employee Harold Ishida>, <Employee Scarlett Winter>, <Employee Emily Vill>, <Employee Mary Park>]
Recuperando el Primer Registro
De manera similar, puedes usar el método first()
para obtener el primer registro:
La salida será un objeto que contiene los datos del primer empleado:
Output<Employee John Doe>
Recuperando un Registro por ID
En la mayoría de las tablas de bases de datos, los registros se identifican con un ID único. Flask-SQLAlchemy te permite recuperar un registro utilizando su ID con el método get()
:
Output<Employee James White> | ID: 5
<Employee Jane Tanaka> | ID: 3
Obtención de un registro o varios registros por el valor de una columna
Para obtener un registro usando el valor de una de sus columnas, utiliza el método filter_by()
. Por ejemplo, para obtener un registro usando su valor de ID, similar al método get()
:
Output<Employee John Doe>
Usas first()
porque filter_by()
puede devolver múltiples resultados.
Nota: Para obtener un registro por ID, usar el método get()
es un enfoque mejor.
Por otro ejemplo, puedes obtener un empleado usando su edad:
Output<Employee Harold Ishida>
Para un ejemplo donde el resultado de la consulta contiene más de un registro coincidente, usa la columna firstname
y el primer nombre Mary
, que es un nombre compartido por dos empleados:
Output[<Employee Mary Doe>, <Employee Mary Park>]
Aquí, usas all()
para obtener la lista completa. También puedes usar first()
para obtener solo el primer resultado:
Output<Employee Mary Doe>
Has obtenido registros a través de los valores de las columnas. A continuación, consultarás tu tabla usando condiciones lógicas.
Paso 3 — Filtrar registros usando condiciones lógicas
En aplicaciones web complejas y completas, a menudo necesitas consultar registros de la base de datos utilizando condiciones complicadas, como buscar empleados basados en una combinación de condiciones que tengan en cuenta su ubicación, disponibilidad, rol y responsabilidades. En este paso, practicarás el uso de operadores condicionales. Usarás el método filter()
en el atributo query
para filtrar los resultados de la consulta utilizando condiciones lógicas con diferentes operadores. Por ejemplo, puedes usar operadores lógicos para obtener una lista de qué empleados están actualmente fuera de la oficina, o empleados que están por ser promovidos, y tal vez proporcionar un calendario del tiempo de vacaciones de los empleados, etc.
Igual
El operador lógico más simple que puedes usar es el operador de igualdad ==
, que se comporta de manera similar a filter_by()
. Por ejemplo, para obtener todos los registros donde el valor de la columna firstname
es Mary
, puedes usar el método filter()
de la siguiente manera:
Aquí utilizas la sintaxis Modelo.columna == valor
como argumento para el método filter()
. El método filter_by()
es un atajo para esta sintaxis.
El resultado es el mismo que el resultado del método filter_by()
con la misma condición:
Output[<Employee Mary Doe>, <Employee Mary Park>]
Al igual que filter_by()
, también puedes usar el método first()
para obtener el primer resultado:
Output<Employee Mary Doe>
No Igual
El método filter()
te permite usar el operador !=
de Python para obtener registros. Por ejemplo, para obtener una lista de empleados fuera de la oficina, puedes utilizar el siguiente enfoque:
Output[<Employee Jane Tanaka>, <Employee Harold Ishida>]
Aquí utilizas la condición Empleado.activo != True
para filtrar los resultados.
Menor Que
Puedes usar el operador <
para obtener un registro donde el valor de una columna dada sea menor que el valor dado. Por ejemplo, para obtener una lista de empleados menores de 32 años:
Output
Alex Brown
Age: 29
----
James White
Age: 24
----
Scarlett Winter
Age: 22
----
Emily Vill
Age: 27
----
Mary Park
Age: 30
----
Utiliza el operador <=
para registros que sean menores o iguales al valor dado. Por ejemplo, para incluir empleados de 32 años en la consulta anterior:
Output
John Doe
Age: 32
----
Jane Tanaka
Age: 32
----
Alex Brown
Age: 29
----
James White
Age: 24
----
Scarlett Winter
Age: 22
----
Emily Vill
Age: 27
----
Mary Park
Age: 30
----
Mayor Que
De manera similar, el operador >
obtiene un registro donde el valor de una columna dada sea mayor que el valor dado. Por ejemplo, para obtener empleados mayores de 32 años:
OutputMary Doe
Age: 38
----
Harold Ishida
Age: 52
----
Y el operador >=
es para registros que sean mayores o iguales al valor dado. Por ejemplo, puedes incluir nuevamente empleados de 32 años en la consulta anterior:
Output
John Doe
Age: 32
----
Mary Doe
Age: 38
----
Jane Tanaka
Age: 32
----
Harold Ishida
Age: 52
----
En
SQLAlchemy también proporciona una forma de obtener registros donde el valor de una columna coincide con un valor de una lista dada de valores usando el método in_()
en la columna de la siguiente manera:
Output[<Employee Mary Doe>, <Employee Alex Brown>, <Employee Emily Vill>, <Employee Mary Park>]
Aquí, se utiliza una condición con la sintaxis Modelo.columna.in_(iterable)
, donde iterable
puede ser cualquier tipo de objeto por el que puedas iterar. Por otro ejemplo, puedes usar la función range()
de Python para obtener empleados dentro de un rango de edades específico. La siguiente consulta obtiene todos los empleados que están en sus treintas.
OutputJohn Doe
Age: 32
----
Mary Doe
Age: 38
----
Jane Tanaka
Age: 32
----
Mary Park
Age: 30
----
No En
Similar al método in_()
, puedes usar el método not_in()
para obtener registros donde el valor de una columna no esté en un iterable dado:
Output
[<Employee John Doe>, <Employee Jane Tanaka>, <Employee James White>, <Employee Harold Ishida>, <Employee Scarlett Winter>]
Aquí, obtienes todos los empleados excepto aquellos con un primer nombre en la lista names
.
Y
Puedes unir varias condiciones usando la función db.and_()
, que funciona como el operador y
de Python.
Por ejemplo, digamos que quieres obtener todos los empleados que tienen 32 años y que están actualmente activos. Primero, puedes verificar quién tiene 32 años usando el método filter_by()
(también puedes usar filter()
si lo prefieres):
Output<Employee John Doe>
Age: 32
Active: True
-----
<Employee Jane Tanaka>
Age: 32
Active: False
-----
Aquí, ves que John y Jane son los empleados que tienen 32 años. John está activo y Jane está fuera de la oficina.
Para obtener los empleados que tienen 32 años y están activos, usarás dos condiciones con el método filter()
:
Employee.age == 32
Employee.active == True
Para unir estas dos condiciones, usa la función db.and_()
de la siguiente manera:
Output[<Employee John Doe>]
Aquí, utilizas la sintaxis filter(db.and_(condición1, condición2))
.
Usando all()
en la consulta devuelve una lista de todos los registros que coinciden con las dos condiciones. Puedes usar el método first()
para obtener el primer resultado:
Output<Employee John Doe>
Para un ejemplo más complejo, puedes usar db.and_()
con la función date()
para obtener empleados que fueron contratados en un período de tiempo específico. En este ejemplo, obtienes todos los empleados contratados en el año 2019:
Output<Employee Alex Brown> | Hired: 2019-01-03
<Employee Emily Vill> | Hired: 2019-06-09
Aquí importas la función date()
y filtras los resultados usando la función db.and_()
para combinar las siguientes dos condiciones:
Employee.hire_date >= date(year=2019, month=1, day=1)
: Esto esTrue
para empleados contratados el primero de enero de 2019 o después.Employee.hire_date < date(year=2020, month=1, day=1)
: Esto esTrue
para empleados contratados antes del primero de enero de 2020.
Combinar las dos condiciones obtiene empleados contratados desde el primer día de 2019 y antes del primer día de 2020.
O
Similar a db.and_()
, la función db.or_()
combina dos condiciones y se comporta como el operador or
en Python. Obtiene todos los registros que cumplen una de las dos condiciones. Por ejemplo, para obtener empleados de 32 años o 52, puedes combinar dos condiciones con la función db.or_()
de la siguiente manera:
Output<Employee John Doe> | Age: 32
<Employee Jane Tanaka> | Age: 32
<Employee Harold Ishida> | Age: 52
También puedes usar los métodos startswith()
y endswith()
en valores de cadena en condiciones que pases al método filter()
. Por ejemplo, para obtener todos los empleados cuyo nombre comience con la cadena 'M'
y aquellos con un apellido que termine con la cadena 'e'
:
Output<Employee John Doe>
<Employee Mary Doe>
<Employee James White>
<Employee Mary Park>
Aquí combinas las siguientes dos condiciones:
Employee.firstname.startswith('M')
: Coincide con empleados cuyo nombre comienza con'M'
.Employee.lastname.endswith('e')
: Coincide con empleados cuyo apellido termina con'e'
.
Ahora puedes filtrar los resultados de la consulta utilizando condiciones lógicas en tus aplicaciones Flask-SQLAlchemy. A continuación, ordenarás, limitarás y contarás los resultados que obtengas de la base de datos.
Paso 4 — Ordenar, Limitar y Contar Resultados
En las aplicaciones web, a menudo necesitas ordenar tus registros al mostrarlos. Por ejemplo, podrías tener una página para mostrar las últimas contrataciones en cada departamento para que el resto del equipo se entere de las nuevas contrataciones, o puedes ordenar a los empleados mostrando primero las contrataciones más antiguas para reconocer a los empleados con más antigüedad. También necesitarás limitar tus resultados en ciertos casos, como mostrar solo las tres últimas contrataciones en una pequeña barra lateral. Y a menudo necesitas contar los resultados de una consulta, por ejemplo, para mostrar el número de empleados que están actualmente activos. En este paso, aprenderás cómo ordenar, limitar y contar resultados.
Ordenando Resultados
Para ordenar resultados usando los valores de una columna específica, utiliza el método order_by()
. Por ejemplo, para ordenar resultados por el nombre de pila de los empleados:
Output[<Employee Alex Brown>, <Employee Emily Vill>, <Employee Harold Ishida>, <Employee James White>, <Employee Jane Tanaka>, <Employee John Doe>, <Employee Mary Doe>, <Employee Mary Park>, <Employee Scarlett Winter>]
Como muestra la salida, los resultados están ordenados alfabéticamente por el nombre de pila del empleado.
Puedes ordenar por otras columnas. Por ejemplo, puedes usar el apellido para ordenar a los empleados:
Output[<Employee Alex Brown>, <Employee John Doe>, <Employee Mary Doe>, <Employee Harold Ishida>, <Employee Mary Park>, <Employee Jane Tanaka>, <Employee Emily Vill>, <Employee James White>, <Employee Scarlett Winter>]
También puedes ordenar a los empleados por su fecha de contratación:
Output
Harold Ishida 2002-03-06
John Doe 2012-03-03
Jane Tanaka 2015-09-12
Mary Doe 2016-06-07
Alex Brown 2019-01-03
Emily Vill 2019-06-09
James White 2021-02-04
Scarlett Winter 2021-04-07
Mary Park 2021-08-11
Como muestra la salida, esto ordena los resultados desde la contratación más temprana hasta la más reciente. Para revertir el orden y hacerlo descendente desde la contratación más reciente hasta la más temprana, utiliza el método desc()
de la siguiente manera:
OutputMary Park 2021-08-11
Scarlett Winter 2021-04-07
James White 2021-02-04
Emily Vill 2019-06-09
Alex Brown 2019-01-03
Mary Doe 2016-06-07
Jane Tanaka 2015-09-12
John Doe 2012-03-03
Harold Ishida 2002-03-06
También puedes combinar el método order_by()
con el método filter()
para ordenar resultados filtrados. El siguiente ejemplo obtiene todos los empleados contratados en 2021 y los ordena por edad:
OutputScarlett Winter 2021-04-07 | Age 22
James White 2021-02-04 | Age 24
Mary Park 2021-08-11 | Age 30
Aquí, utilizas la función db.and_()
con dos condiciones: Employee.hire_date >= date(year=2021, month=1, day=1)
para empleados contratados el primer día de 2021 o después, y Employee.hire_date < date(year=2022, month=1, day=1)
para empleados contratados antes del primer día de 2022. Luego utilizas el método order_by()
para ordenar a los empleados resultantes por su edad.
Limitando Resultados
En la mayoría de los casos del mundo real, al consultar una tabla de base de datos, podrías obtener hasta millones de resultados coincidentes, y a veces es necesario limitar los resultados a un cierto número. Para limitar resultados en Flask-SQLAlchemy, puedes usar el método limit()
. El siguiente ejemplo consulta la tabla employee
y devuelve solo los primeros tres resultados coincidentes:
Output[<Employee John Doe>, <Employee Mary Doe>, <Employee Jane Tanaka>]
Puedes usar limit()
con otros métodos, como filter
y order_by
. Por ejemplo, puedes obtener los últimos dos empleados contratados en 2021 utilizando el método limit()
de la siguiente manera:
OutputScarlett Winter 2021-04-07 | Age 22
James White 2021-02-04 | Age 24
Aquí, usas la misma consulta en la sección anterior con una llamada de método adicional limit(2)
.
Contando Resultados
Para contar el número de resultados de una consulta, puedes usar el método count()
. Por ejemplo, para obtener el número de empleados que están actualmente en la base de datos:
Output9
Puedes combinar el método count()
con otros métodos de consulta similares a limit()
. Por ejemplo, para obtener el número de empleados contratados en 2021:
Output3
Aquí usas la misma consulta que usaste anteriormente para obtener todos los empleados que fueron contratados en 2021. Y utilizas count()
para recuperar el número de entradas, que es 3.
Has ordenado, limitado y contado los resultados de la consulta en Flask-SQLAlchemy. A continuación, aprenderás cómo dividir los resultados de la consulta en múltiples páginas y cómo crear un sistema de paginación en tus aplicaciones Flask.
Paso 5 — Mostrar Listas de Registros Largos en Múltiples Páginas
En este paso, modificarás la ruta principal para que la página de índice muestre empleados en múltiples páginas para facilitar la navegación por la lista de empleados.
Primero, usarás la shell de Flask para ver una demostración de cómo utilizar la función de paginación en Flask-SQLAlchemy. Abre la shell de Flask si aún no lo has hecho:
Digamos que deseas dividir los registros de empleados en tu tabla en varias páginas, con dos elementos por página. Puedes hacer esto usando el método de consulta paginate()
de la siguiente manera:
Output<flask_sqlalchemy.Pagination object at 0x7f1dbee7af80>
[<Employee John Doe>, <Employee Mary Doe>]
Utilizas el parámetro page
del método de consulta paginate()
para especificar la página a la que deseas acceder, que en este caso es la primera página. El parámetro per_page
especifica el número de elementos que debe tener cada página. En este caso, lo estableces en 2
para que cada página tenga dos elementos.
La variable page1
aquí es un objeto de paginación, que te da acceso a atributos y métodos que utilizarás para gestionar tu paginación.
Accedes a los elementos de la página utilizando el atributo items
.
Para acceder a la página siguiente, puedes utilizar el método next()
del objeto de paginación de la siguiente manera, el resultado devuelto también es un objeto de paginación:
Output[<Employee Jane Tanaka>, <Employee Alex Brown>]
<flask_sqlalchemy.Pagination object at 0x7f1dbee799c0>
Puedes obtener un objeto de paginación para la página anterior utilizando el método prev()
. En el siguiente ejemplo, accedes al objeto de paginación para la cuarta página, luego accedes al objeto de paginación de su página anterior, que es la página 3:
Output[<Employee Scarlett Winter>, <Employee Emily Vill>]
[<Employee James White>, <Employee Harold Ishida>]
Puedes acceder al número de página actual utilizando el atributo page
de la siguiente manera:
Output1
2
Para obtener el número total de páginas, utiliza el atributo pages
del objeto de paginación. En el siguiente ejemplo, tanto page1.pages
como page2.pages
devuelven el mismo valor porque el número total de páginas es constante:
Output5
5
Para el número total de elementos, utiliza el atributo total
del objeto de paginación:
Output9
9
Aquí, dado que consultas todos los empleados, el número total de elementos en la paginación es 9, porque hay nueve empleados en la base de datos.
A continuación se muestran algunos de los otros atributos que tienen los objetos de paginación:
prev_num
: El número de página anterior.next_num
: El número de página siguiente.has_next
:True
si hay una página siguiente.has_prev
:True
si hay una página anterior.per_page
: El número de elementos por página.
El objeto de paginación también tiene un método iter_pages()
que puedes recorrer para acceder a los números de página. Por ejemplo, puedes imprimir todos los números de página así:
Output1
2
3
4
5
Lo siguiente es una demostración de cómo acceder a todas las páginas y sus elementos utilizando un objeto de paginación y el método iter_pages()
:
Output
PAGE 1
-
[<Employee John Doe>, <Employee Mary Doe>]
--------------------
PAGE 2
-
[<Employee Jane Tanaka>, <Employee Alex Brown>]
--------------------
PAGE 3
-
[<Employee James White>, <Employee Harold Ishida>]
--------------------
PAGE 4
-
[<Employee Scarlett Winter>, <Employee Emily Vill>]
--------------------
PAGE 5
-
[<Employee Mary Park>]
--------------------
Aquí, creas un objeto de paginación que comienza desde la primera página. Recorres las páginas utilizando un bucle for
con el método de paginación iter_pages()
. Imprimes el número de página y los elementos de la página, y estableces el objeto pagination
en el objeto de paginación de su siguiente página utilizando el método next()
.
También puedes usar los métodos filter()
y order_by()
con el método paginate()
para paginar los resultados de consultas filtradas y ordenadas. Por ejemplo, puedes obtener empleados mayores de treinta años y ordenar los resultados por edad y paginar los resultados así:
OutputPAGE 1
-
<Employee John Doe> | Age: 32
<Employee Jane Tanaka> | Age: 32
--------------------
PAGE 2
-
<Employee Mary Doe> | Age: 38
<Employee Harold Ishida> | Age: 52
--------------------
Ahora que tienes una comprensión sólida de cómo funciona la paginación en Flask-SQLAlchemy, editarás la página de índice de tu aplicación para mostrar empleados en múltiples páginas para una navegación más fácil.
Salir del shell de Flask:
Para acceder a diferentes páginas, utilizarás parámetros de URL, también conocidos como cadenas de consulta de URL, que son una forma de pasar información a la aplicación a través de la URL. Los parámetros se pasan a la aplicación en la URL después de un símbolo ?
. Por ejemplo, para pasar un parámetro page
con diferentes valores, puedes usar las siguientes URLs:
http://127.0.0.1:5000/?page=1
http://127.0.0.1:5000/?page=3
Aquí, la primera URL pasa el valor 1
al parámetro de URL page
. La segunda URL pasa el valor 3
al mismo parámetro.
Abrir el archivo app.py
:
Editar la ruta del índice para que se vea de la siguiente manera:
Aquí, obtienes el valor del parámetro de URL page
utilizando el objeto request.args
y su método get()
. Por ejemplo, /?page=1
obtendrá el valor 1
del parámetro de URL page
. Pasas 1
como un valor predeterminado y pasas el tipo de Python int
como argumento al parámetro type
para asegurarte de que el valor sea un entero.
A continuación, creas un objeto pagination
, ordenando los resultados de la consulta por el primer nombre. Pasas el valor del parámetro de URL page
al método paginate()
, y divides los resultados en dos elementos por página al pasar el valor 2
al parámetro per_page
.
Por último, pasas el objeto pagination
que has construido a la plantilla index.html
renderizada.
Guarda y cierra el archivo.
A continuación, edita la plantilla index.html
para mostrar los elementos de paginación:
Cambia la etiqueta div
de contenido agregando un encabezado h2
que indique la página actual, y cambia el bucle for
para iterar sobre el objeto pagination.items
en lugar del objeto employees
, que ya no está disponible.
Guarda y cierra el archivo.
Si aún no lo has hecho, establece las variables de entorno FLASK_APP
y FLASK_ENV
y ejecuta el servidor de desarrollo:
Ahora, navega hasta la página de índice con diferentes valores para el parámetro de URL page
:
http://127.0.0.1:5000/
http://127.0.0.1:5000/?page=2
http://127.0.0.1:5000/?page=4
http://127.0.0.1:5000/?page=19
Verás diferentes páginas con dos elementos cada una, y diferentes elementos en cada página, como has visto anteriormente en la shell de Flask.
Si el número de página dado no existe, obtendrás un error HTTP 404 Not Found
, como es el caso con la última URL en la lista de URL anterior.
A continuación, crearás un widget de paginación para navegar entre páginas, utilizarás algunos atributos y métodos del objeto de paginación para mostrar todos los números de página, cada número enlazará a su página dedicada, y un botón <<<
para retroceder si la página actual tiene una página anterior, y un botón >>>
para ir a la siguiente página si existe.
El widget de paginación se verá de la siguiente manera:
Para añadirlo, abre index.html
:
Edita el archivo añadiendo la siguiente div
resaltada debajo de la div
de contenido:
Guarda y cierra el archivo.
Aquí, utilizas la condición if pagination.has_prev
para añadir un enlace <<<
a la página anterior si la página actual no es la primera. Enlazas a la página anterior usando la llamada a la función url_for('index', page=pagination.prev_num)
, en la cual enlazas a la función de vista de índice, pasando el valor pagination.prev_num
al parámetro URL page
.
Para mostrar enlaces a todos los números de página disponibles, recorres los elementos del método pagination.iter_pages()
que te proporciona un número de página en cada iteración.
Utilizas la condición if pagination.page != número
para verificar si el número de página actual no es igual al número en el bucle actual. Si la condición es verdadera, enlazas a la página para permitir al usuario cambiar la página actual a otra página. De lo contrario, si la página actual es la misma que el número del bucle, muestras el número sin un enlace. Esto permite a los usuarios saber el número de página actual en el widget de paginación.
Por último, utilizas la condición pagination.has_next
para verificar si la página actual tiene una página siguiente, en cuyo caso enlazas a ella utilizando la llamada url_for('index', page=pagination.next_num)
y un enlace >>>
.
Navega a la página de índice en tu navegador: http://127.0.0.1:5000/
Verás que el widget de paginación está completamente funcional:
Aquí, utilizas >>>
para moverte a la siguiente página y <<<
para la página anterior, pero también puedes usar cualquier otro carácter que desees, como >
y <
o imágenes en etiquetas <img>
.
Has mostrado empleados en múltiples páginas y aprendido cómo manejar la paginación en Flask-SQLAlchemy. Y ahora puedes usar tu widget de paginación en otras aplicaciones de Flask que construyas.
Conclusión
Utilizaste Flask-SQLAlchemy para crear un sistema de gestión de empleados. Consultaste una tabla y filtraste resultados basados en valores de columnas y condiciones lógicas simples y complejas. Ordenaste, contaste y limitaste resultados de consultas. Y creaste un sistema de paginación para mostrar un cierto número de registros en cada página de tu aplicación web, y navegar entre páginas.
Puedes utilizar lo que has aprendido en este tutorial en combinación con conceptos explicados en algunos de nuestros otros tutoriales de Flask-SQLAlchemy para agregar más funcionalidad a tu sistema de gestión de empleados:
- Cómo usar Flask-SQLAlchemy para interactuar con bases de datos en una aplicación Flask para aprender cómo agregar, editar o eliminar empleados.
- Cómo usar relaciones de base de datos uno a muchos con Flask-SQLAlchemy para aprender cómo usar relaciones uno a muchos para crear una tabla de departamentos para vincular a cada empleado con el departamento al que pertenecen.
- Cómo utilizar relaciones de muchos a muchos en bases de datos con Flask-SQLAlchemy para aprender a utilizar relaciones de muchos a muchos para crear una tabla
tasks
y vincularla a la tablaemployee
, donde cada empleado tiene muchas tareas y cada tarea está asignada a múltiples empleados.
Si deseas leer más sobre Flask, consulta los otros tutoriales en la serie Cómo Construir Aplicaciones Web con Flask.