0% encontró este documento útil (0 votos)
61 vistas12 páginas

Gestión de Empleados con Flask y Python

Este documento describe una aplicación web de gestión de empleados desarrollada con Python y Flask. Permite funciones CRUD para empleados, registro y autenticación de usuarios, y generación de informes. Se implementó siguiendo el patrón MVC con Flask, HTML, CSS, JavaScript y MySQL. El código fuente incluye configuración de Flask, rutas, conexión a la base de datos, y funciones para el manejo de empleados.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
61 vistas12 páginas

Gestión de Empleados con Flask y Python

Este documento describe una aplicación web de gestión de empleados desarrollada con Python y Flask. Permite funciones CRUD para empleados, registro y autenticación de usuarios, y generación de informes. Se implementó siguiendo el patrón MVC con Flask, HTML, CSS, JavaScript y MySQL. El código fuente incluye configuración de Flask, rutas, conexión a la base de datos, y funciones para el manejo de empleados.
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd

Documentación del Proyecto

Descripción de la Aplicación
La aplicación es un sistema de gestión de empleados (CRUD) desarrollado con
Python utilizando el framework Flask. Permite a los usuarios registrar una cuenta,
iniciar sesión, agregar, modificar, buscar, eliminar y actualizar empleados, generar un
reporte en formato Excel y actualizar su perfil.

Tecnologías Utilizadas
● Python: Utilizado como lenguaje de programación principal.
● Flask: Framework de desarrollo web utilizado para crear el backend de la
aplicación.
● Frontend: HTML, CSS, JavaScript: Utilizados para desarrollar la interfaz de
usuario y la experiencia del cliente.
● Visual Studio Code: Entorno de desarrollo integrado (IDE) utilizado para escribir,
editar y depurar el código.
● MySQL Workbench: Herramienta de diseño y administración de bases de datos
utilizada para gestionar la base de datos MySQL.

Decisiones de Diseño
● Arquitectura MVC (Modelo-Vista-Controlador): Se siguió el patrón de diseño
MVC para organizar el código de la aplicación de manera modular y separar las
preocupaciones.
● Interfaz de Usuario Amigable (UI): Se diseñó una interfaz de usuario intuitiva y
fácil de usar para que los usuarios puedan interactuar de manera eficiente con la
aplicación.
● Seguridad: Se implementaron medidas de seguridad como el cifrado de
contraseñas para proteger la información sensible de los usuarios.
● Reporte en Excel: Se agregó la funcionalidad de generar un reporte en formato
Excel para proporcionar a los usuarios una forma conveniente de exportar y
analizar datos.

Funcionalidades Principales
● Registro de cuenta: Permite a los usuarios crear una cuenta proporcionando su
nombre, dirección de correo electrónico y contraseña.
● Inicio de Sesión y Cierre de Sesión: Los usuarios pueden iniciar sesión en sus
cuentas existentes y cerrar sesión cuando haya terminado de usar la aplicación.
● CRUD de Empleados: Los usuarios pueden realizar operaciones CRUD (Crear,
Leer, Actualizar, Eliminar) en los datos de los empleados.
● Gestión de Usuarios: Los usuarios pueden ver registros de otros usuarios,
incluidos los detalles de la fecha y hora de creación de la cuenta.
● Generación de Reporte en Excel: Se proporciona una función para generar un
reporte en formato Excel que contiene datos relevantes sobre los empleados.
● Actualización de Perfil: Los usuarios pueden ver su perfil y actualizar su
información personal si es necesario.

Diseño de la Arquitectura de la Aplicación


● Estructura de la Base de Datos: Se diseñó una estructura de base de datos
relacional utilizando MySQL para almacenar la información de los usuarios y los
empleados.
● Definición de Rutas en el Backend: Se crearon rutas en el backend de la
aplicación utilizando Flask para manejar las solicitudes HTTP y realizar
operaciones en la base de datos.

Implementación
● Funcionalidades CRUD en el Backend: Se implementan las funcionalidades
CRUD en el backend utilizando Python y Flask para manipular los datos de los
empleados en la base de datos.
● Desarrollo de la Interfaz de Usuario en el Frontend: Se desarrolló la interfaz de
usuario en el frontend utilizando HTML, CSS y JavaScript para crear una
experiencia de usuario atractiva y fácil de usar.
● Integración Frontend y Backend: Se integró el frontend con el backend para
permitir la comunicación entre ambas partes de la aplicación, permitiendo a los
usuarios interactuar con los datos de manera eficiente.

Código Fuente
Configuración inicial de la aplicación Flask
from flask import Flask
# Creación de la aplicación Flask
app = Flask(__name__)
# Alias para la aplicación, útil para algunos servidores web
application = app
# Clave secreta para mantener segura la sesión del usuario
app.secret_key =
'97110c78ae51a45af397b6534caef90ebb9b1dcb3380f008f90b23a5d1616bf1bc29098105da20f
e'
Archivo de ejecución de la aplicación Flask
# Importando la aplicación Flask desde el archivo [Link]
from app import app
# Importando las rutas desde diferentes archivos de enrutamiento
from routers.router_login import *
from routers.router_home import *
from routers.router_page_not_found import *
# Ejecutando la aplicación Flask
if __name__ == '__main__':
# Iniciando la aplicación en modo de depuración y en el puerto 5600
[Link](debug=True, port=5600)

Script MYSQL para la creación de la base de datos


-- Crear la base de datos crud_python si no existe
CREATE DATABASE IF NOT EXISTS `crud_python` /*!40100 DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci */ /*!80016 DEFAULT ENCRYPTION='N' */;
USE `crud_python`;
-- Crear la tabla tbl_empleados
CREATE TABLE IF NOT EXISTS `tbl_empleados` (
`id_empleado` int NOT NULL AUTO_INCREMENT,
`nombre_empleado` varchar(50) DEFAULT NULL,
`apellido_empleado` varchar(50) DEFAULT NULL,
`sexo_empleado` int DEFAULT NULL,
`telefono_empleado` varchar(50) DEFAULT NULL,
`email_empleado` varchar(50) DEFAULT NULL,
`profesion_empleado` varchar(50) DEFAULT NULL,
`foto_empleado` mediumtext,
`salario_empleado` bigint DEFAULT NULL,
`fecha_registro` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id_empleado`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_0900_ai_ci;
-- Insertar datos de ejemplo en la tabla tbl_empleados
INSERT INTO `tbl_empleados` VALUES
(4,'Urian','Viera',1,'54544454','programadorphp2017@[Link]','Ingeniero de
Sistemas','[Link]',3500000,'20
23-08-23
[Link]'),(5,'Brenda','Viera',2,'323543543','brenda@[Link]','Dev','22c055aeec314572a0046ec50b84
[Link]',1200000,'2023-08-23
[Link]'),(6,'Alejandro','Torres',1,'324242342','alejandro@[Link]','Tecnico','7b84aceb56534d27aa2e
[Link]',2100,'2023-08-23
[Link]'),(7,'Karla','Ramos',2,'345678','karla@[Link]','Ingeniera','248cc9c38cfb494bb2300d7cbf4a3b
[Link]',2300,'2023-08-23 [Link]');
-- Crear la tabla users
CREATE TABLE IF NOT EXISTS `users` (
`id` int NOT NULL AUTO_INCREMENT,
`name_surname` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`email_user` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`pass_user` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`created_user` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4
COLLATE=utf8mb4_general_ci;
-- Insertar datos de ejemplo en la tabla users
INSERT INTO `users` (`id`, `name_surname`, `email_user`, `pass_user`, `created_user`) VALUES
(1, 'Urian', 'dev@[Link]',
'scrypt:3[Link]$ZXqvqovbXYQZdrAB$66758083429739f4f8985992b22cb89fb58c04b99010858e7fb26f
73078a23dd3e16019a17bf881108d582a91a635d2c21d26d80da1612c2d9c9bbb9b06452dc', '2023-07-21
[Link]'),
(2, 'demo', 'demo@[Link]',
'scrypt:3[Link]$Yl2tGU1Ru1Q4Jrzq$d88a0ded538dcfc3a01c8ebf4ea77700576203f6a7cc765f0462746
4c6047bdcf8eaad84ca3cf0bb5ed058d2dff8ee7a0ba690803538764bedc3ba6173ac6a8a', '2023-07-21
[Link]');

Establecimiento de conexión con la base de datos MySQL en Python


# Importando la librería [Link] para conectar Python con MySQL
import [Link]

def connectionBD():
try:
# Estableciendo la conexión con la base de datos
connection = [Link](
host='localhost', # Dirección del servidor de la base de datos
user='root', # Usuario de la base de datos
passwd='Alexis_1234', # Contraseña del usuario
database='crud_python', # Nombre de la base de datos
port='3306', # Puerto de la base de datos
charset='utf8mb4', # Conjunto de caracteres
collation='utf8mb4_unicode_ci', # Colación de la base de datos
raise_on_warnings=True # Generar excepción si hay advertencias
)
if connection.is_connected():
# Si la conexión se estableció correctamente, retorna el objeto de conexión
return connection
except [Link] as error:
# Manejo de errores en caso de que la conexión falle
print(f"No se pudo conectar: {error}")

Funciones para el manejo de empleados en el backend


# Función para procesar el formulario de registro de un nuevo empleado
def procesar_form_empleado(dataForm, foto_perfil):
"""
Procesa el formulario de registro de un nuevo empleado.
Parameters:
dataForm (dict): Datos del formulario de registro.
foto_perfil (FileStorage): Imagen de perfil del empleado.
Returns:
int: Número de filas afectadas por la operación de inserción.
"""
# Eliminar puntos del salario y convertir a entero
salario_sin_puntos = [Link]('[^0-9]+', '', dataForm['salario_empleado'])
salario_entero = int(salario_sin_puntos)
# Procesar y obtener el nombre del archivo de la foto de perfil
result_foto_perfil = procesar_imagen_perfil(foto_perfil)
try:
# Establecer conexión con la base de datos
with connectionBD() as conexion_MySQLdb:
with conexion_MySQLdb.cursor(dictionary=True) as cursor:
# Query SQL para insertar un nuevo empleado en la base de datos
sql = "INSERT INTO tbl_empleados (nombre_empleado, apellido_empleado, sexo_empleado,
telefono_empleado, email_empleado, profesion_empleado, foto_empleado, salario_empleado) VALUES
(%s, %s, %s, %s, %s, %s, %s, %s)"
# Valores a insertar en la tabla de empleados
valores = (dataForm['nombre_empleado'], dataForm['apellido_empleado'],
dataForm['sexo_empleado'], dataForm['telefono_empleado'], dataForm['email_empleado'],
dataForm['profesion_empleado'], result_foto_perfil, salario_entero)
# Ejecutar la consulta SQL
[Link](sql, valores)
# Confirmar los cambios en la base de datos
conexion_MySQLdb.commit()
# Obtener el número de filas afectadas por la inserción
resultado_insert = [Link]
return resultado_insert
except Exception as e:
# Manejo de errores
return f'Se produjo un error en procesar_form_empleado: {str(e)}'
# Función para procesar y almacenar la imagen de perfil del empleado
def procesar_imagen_perfil(foto):
"""
Procesa y almacena la imagen de perfil del empleado en el servidor.
Parameters:
foto (FileStorage): Imagen de perfil del empleado.
Returns:
str: Nombre del archivo almacenado.
"""
try:
# Obtener el nombre original del archivo y su extensión
filename = secure_filename([Link])
extension = [Link](filename)[1]
# Generar un nombre único para el archivo
nuevoNameFile = (uuid.uuid4().hex + uuid.uuid4().hex)[:100]
nombreFile = nuevoNameFile + extension
# Obtener la ruta del directorio de almacenamiento
basepath = [Link]([Link](__file__))
upload_dir = [Link](basepath, f'../static/fotos_empleados/')
# Verificar si el directorio de almacenamiento existe, si no, crearlo
if not [Link](upload_dir):
[Link](upload_dir)
[Link](upload_dir, 0o755)
# Construir la ruta completa del archivo a almacenar
upload_path = [Link](upload_dir, nombreFile)
# Guardar la imagen en el servidor
[Link](upload_path)
# Retornar el nombre del archivo almacenado
return nombreFile
except Exception as e:
# Manejo de errores
print("Error al procesar archivo:", e)
return []

Funciones de Gestión de Usuarios y Sesiones


# Importandopaquetes desde flask
from flask import session, flash
# Importando conexion a BD
from [Link] import connectionBD
# Para validar contraseña
from [Link] import check_password_hash
import re
def recibeInsertRegisterUser(name_surname, email_user, pass_user):
# Función para registrar un nuevo usuario en la base de datos
# Implementación omitida por brevedad
def validarDataRegisterLogin(name_surname, email_user, pass_user):
# Función para validar los datos de registro/login de un usuario
# Implementación omitida por brevedad
def info_perfil_session():
# Función para obtener la información del perfil de usuario de la sesión actual
# Implementación omitida por brevedad
def procesar_update_perfil(data_form):
# Función para procesar la actualización del perfil de usuario
# Implementación omitida por brevedad
def updatePefilSinPass(id_user, name_surname):
# Función auxiliar para actualizar el perfil de usuario sin cambiar la contraseña
# Implementación omitida por brevedad
def dataLoginSesion():
# Función para obtener la información de inicio de sesión del usuario
# Implementación omitida por brevedad

Gestión de Empleados y Usuarios en Flask


from app import app
from flask import render_template, request, flash, redirect, url_for, session, jsonify
from controllers.funciones_home import * # Importa las funciones relacionadas con la gestión
de empleados desde el controlador
# Rutas para las diferentes funcionalidades relacionadas con la gestión de empleados y
usuarios
# Ruta para mostrar el formulario de registro de un nuevo empleado
@[Link]('/registrar-empleado', methods=['GET'])
def viewFormEmpleado():
# Verifica si el usuario está conectado
if 'conectado' in session:
return render_template(f'{PATH_URL}/form_empleado.html') # Renderiza el formulario de
registro de empleado
else:
flash('primero debes iniciar sesión.', 'error') # Muestra un mensaje de error si el usuario no
está conectado
return redirect(url_for('inicio')) # Redirige al usuario a la página de inicio de sesión
# Ruta para procesar el formulario de registro de un nuevo empleado
@[Link]('/form-registrar-empleado', methods=['POST'])
def formEmpleado():
# Verifica si el usuario está conectado
if 'conectado' in session:
# Verifica si se ha enviado una foto de perfil junto con el formulario
if 'foto_empleado' in [Link]:
foto_perfil = [Link]['foto_empleado'] # Obtiene la foto de perfil enviada en el
formulario
resultado = procesar_form_empleado([Link], foto_perfil) # Procesa el formulario
de registro de empleado
if resultado:
return redirect(url_for('lista_empleados')) # Redirige al usuario a la lista de
empleados después de registrar al nuevo empleado
else:
flash('El empleado NO fue registrado.', 'error') # Muestra un mensaje de error si el
empleado no pudo ser registrado
return render_template(f'{PATH_URL}/form_empleado.html') # Renderiza
nuevamente el formulario de registro de empleado
else:
flash('primero debes iniciar sesión.', 'error') # Muestra un mensaje de error si el usuario no
está conectado
return redirect(url_for('inicio')) # Redirige al usuario a la página de inicio de sesión
# Otras rutas y funciones de manejo de empleados y usuarios...

Gestión de Sesión y Autenticación en Flask


from app import app
from flask import render_template, request, flash, redirect, url_for, session
from [Link] import connectionBD
from [Link] import check_password_hash
from controllers.funciones_login import *
# Ruta para la página de inicio
@[Link]('/', methods=['GET'])
def inicio():
if 'conectado' in session: # Verifica si el usuario está conectado
return render_template('public/base_cpanel.html', dataLogin=dataLoginSesion())
else:
return render_template('public/login/base_login.html') # Si no, muestra la página de inicio
de sesión
# Otras rutas...
# Ruta para el inicio de sesión
@[Link]('/login', methods=['GET', 'POST'])
def loginCliente():
if 'conectado' in session: # Si ya está conectado, redirige a la página de inicio
return redirect(url_for('inicio'))
else:
if [Link] == 'POST' and 'email_user' in [Link] and 'pass_user' in
[Link]:
email_user = str([Link]['email_user'])
pass_user = str([Link]['pass_user'])
conexion_MySQLdb = connectionBD() # Conexión a la base de datos
cursor = conexion_MySQLdb.cursor(dictionary=True)
[Link]("SELECT * FROM users WHERE email_user = %s", [email_user])
account = [Link]() # Busca la cuenta en la base de datos
if account:
if check_password_hash(account['pass_user'], pass_user): # Comprueba la
contraseña
session['conectado'] = True # Establece la sesión como conectada
session['id'] = account['id']
session['name_surname'] = account['name_surname']
session['email_user'] = account['email_user']
flash('La sesión fue correcta.', 'success') # Muestra un mensaje de éxito
return redirect(url_for('inicio'))
else:
flash('Datos incorrectos. Por favor, revise.', 'error') # Muestra un mensaje de error
return render_template('public/login/base_login.html')
else:
flash('El usuario no existe. Por favor, verifique.', 'error') # Muestra un mensaje de
error
return render_template('public/login/base_login.html')
else:
flash('Primero debes iniciar sesión.', 'error') # Muestra un mensaje de error
return render_template('public/login/base_login.html')
# Otras rutas...
Manejador de error para página no encontrada con redireccionamiento en Flask
from app import app
from flask import request, session, redirect, url_for
# Manejador de error para la página no encontrada (error 404)
@[Link](404)
def page_not_found(error):
if 'conectado' in session and [Link] == 'GET': # Si el usuario está conectado y la
solicitud es GET
return redirect(url_for('inicio')) # Redirige a la página de inicio
else:
return redirect(url_for('inicio')) # De lo contrario, también redirige a la página de inicio

Estilos para la carga y edición de avatares


/* Estilos para la carga y edición de avatares */
/* Contenedor principal del avatar */
.avatar-upload {
position: relative;
max-width: 205px; /* Ancho máximo del contenedor */
}
/* Botón de edición del avatar */
.avatar-upload .avatar-edit {
position: absolute;
right: 12px;
z-index: 1;
top: 10px;
}
/* Input para seleccionar archivo (oculto) */
.avatar-upload .avatar-edit input {
display: none;
}
/* Estilos para el botón de edición */
.avatar-upload .avatar-edit input + label {
display: inline-block;
width: 34px;
height: 34px;
margin-bottom: 0;
border-radius: 100%;
background: #ffffff;
border: 1px solid transparent;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.12);
cursor: pointer;
font-weight: normal;
transition: all 0.2s ease-in-out;
}
/* Estilos para el botón de edición al pasar el cursor por encima */
.avatar-upload .avatar-edit input + label:hover {
background: #f1f1f1;
border-color: #d6d6d6;
}
/* Vista previa del avatar */
.avatar-upload .avatar-preview {
width: 192px;
height: 192px;
position: relative;
border-radius: 100%;
border: 6px solid #f8f8f8;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
}
/* Contenido de la vista previa del avatar */
.avatar-upload .avatar-preview > div {
width: 100%;
height: 100%;
border-radius: 100%;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
/* Estilos adicionales para el ícono de lápiz */
.bi-pen {
padding: 12px;
font-size: 14px;
text-align: center;
color: #222;
}

Función de búsqueda en tabla


// Función asincrónica para buscar en una tabla
async function buscadorTable(tableId) {
let input = [Link]("search");
let busqueda = [Link]();
const url = "/buscando-empleado";
const dataPeticion = { busqueda };
const headers = {
"Content-Type": "application/json",
"Access-Control-Allow-Origin": "*",
};
try {
const response = await [Link](url, dataPeticion, { headers });

😭
if (![Link]) {
[Link](`¡Error HTTP! Estado: ${[Link]} `);
}
if ([Link] === 0) {
$(`#${tableId} tbody`).html(`
<tr>
<td colspan="6" style="text-align:center;color: red;font-weight: bold;">No resultados para
la busqueda: <strong style="text-align:center;color: #222;">${busqueda}</strong></td>
</tr>`);
return false;
}
if ([Link]) {
$(`#${tableId} tbody`).html("");
$(`#${tableId} tbody`).append([Link]);
}
} catch (error) {
[Link](error);
}}

Código para vista previa de imagen y formateo de salario


/**
* Función para mostrar una vista previa de la imagen cargada.
* @param {Object} input - El input de tipo file que contiene la imagen.
*/
function readURL(input) {
if ([Link] && [Link][0]) {
// Obtener la URL de la imagen cargada
var imageUrl = [Link]([Link][0]);
// Mostrar la imagen de vista previa
$("#imagePreview").css("background-image", "url(" + imageUrl + ")");
$("#imagePreview").hide();
$("#imagePreview").fadeIn(650);
}
}
// Evento change para el input de carga de imagen
$("#imageUpload").change(function () {
readURL(this);
});
/**
* Función para formatear la cantidad en salario.
*/
let salario = [Link]("#salario_empleado");
if (salario) {
[Link]("input", (inputClick) => {
// Eliminar caracteres no numéricos y convertir a número entero
let cantidad = [Link](/\D/g, "");
cantidad = parseInt(cantidad, 10);
if (isNaN(cantidad)) {
cantidad = 0;
}
// Formatear la cantidad y asignarla al campo de entrada
[Link] =
"$ " +
[Link]("es-CO", {
minimumFractionDigits: 0,
maximumFractionDigits: 0,
});
});
}

Código JavaScript para Interacciones en la Página de Inicio


/**
* Función para desvanecer un elemento gradualmente hasta que desaparezca.
* @param {HTMLElement} element - El elemento HTML a desvanecer.
*/
function fadeOut(element) {
let opacity = 1;
const timer = setInterval(function () {
if (opacity <= 0.1) {
clearInterval(timer);
[Link] = "none";
}
[Link] = opacity;
opacity -= opacity * 0.1;
}, 50);
}
// Obtener elemento del loader y desvanecerlo
const loaderOut = [Link]("#loader-out");
fadeOut(loaderOut);
/**
* Función para confirmar y eliminar un empleado.
* @param {string} id_empleado - El ID del empleado a eliminar.
* @param {string} foto_empleado - La URL de la foto del empleado.
*/
function eliminarEmpleado(id_empleado, foto_empleado) {
if (confirm("¿Estás seguro que deseas Eliminar el empleado?")) {
let url = `/borrar-empleado/${id_empleado}/${foto_empleado}`;
if (url) {
[Link] = url;
}
}
}

También podría gustarte