Crear aplicación gráfica con Python, MySQL y Tkinter

Crear aplicación gráfica con Python, MySQL y Tkinter

Crear aplicación gráfica con Python, MySQL y Tkinter - Parte 4 - 100 días de Python #29

Continuamos con la cuarta parte del proyecto. En esta ocasión, voy a mostrarte como crear métodos decoradores en clases Python. De esta forma, podremos reutilizar código repetitivo.

Así es como tenemos, de momento, la aplicación:

archivo paquete Python __init__.py

base_datos.py

import mysql.connector

#conexion con la base de datos
acceso_bd = {"host" : "localhost",
             "user" : "root",
             "password" : "programacionfacil",
             }

class BaseDatos:
    #Conexión y cursor
    def __init__(self, **kwargs):
        self.conector = mysql.connector.connect(**kwargs)
        self.cursor = self.conector.cursor()
    
    #Consultas SQL    
    def consulta(self, sql):
        self.cursor.execute(sql)
        return self.cursor
    
    #Mostrar bases de datos
    def mostrar_bd(self):
        self.cursor.execute("SHOW DATABASES")
        for bd in self.cursor:
            print(bd)
             
    #Eliminar bases de datos
    def eliminar_bd(self, nombre_bd):
        try:
            self.cursor.execute(f"DROP DATABASE {nombre_bd}")
            print(f"Se eliminó la base de datos {nombre_bd} correctamente.")
        except:
            print(f"Base de datos '{nombre_bd}' no encontrada.")
            print("Estas son las bases de datos que tiene el servidor:")
            self.mostrar_bd(self)
    
    #método para crear bases de datos
    def crear_bd(self, nombre_bd):
        try:
            self.cursor.execute(f"CREATE DATABASE IF NOT EXISTS {nombre_bd}")
            print(f"Se creó la base de datos {nombre_bd} o ya estaba creada.")
        except:
            print(f"Ocurrió un error al intentar crear la base de datos {nombre_bd}.")
            print("Estas son las bases de datos que tiene el servidor:")
            self.mostrar_bd(self)

app.py

import bd.base_datos as sqlbd
#Objeto de tipo BaseDatos
base_datos = sqlbd.BaseDatos(**sqlbd.acceso_bd)

En el capítulo anterior, deje la siguiente cuestión. Si te fijas, en las líneas 33 y 34, se reporta un print() y una llamada al método para mostrar las bases de datos en el servidor. Solo en caso de que salte el bloque except.

Esto mismo, se repite en las líneas 43 y 44. Entonces, te planteé el reto de intentar escribir esto una sola vez para los dos métodos o para los que vinieran.

Una forma de hacerlo, es mediante un método decorador. No te preocupes si no has conseguido hacerlo, ya que tiene bastante dificultad cuando no has utilizado apenas los decoradores.

Aquí la dificultad añadida, es que estamos dentro de una clase.

Puedes colocar el método decorador debajo del __init__:

#Decoradora para el reporte de bases de datos en el servidor
    def reporte_bd(funcion_parametro):
        def interno(self, nombre_db):
            funcion_parametro(self, nombre_db)
            print("Estas son las bases de datos que tiene el servidor:")
            BaseDatos.mostrar_bd(self)
        return interno

El nombre del método decorador es "reporte_bd". Este nombre, en el capítulo en el cual expliqué las funciones decoradoras, se presentaba como "a" en los ejemplos.

La "funcion_parametro" es la que se representaba como "b".

Y el método "interno" es el que aparecía como "c" en los ejemplos de ese capítulo.

Te cuento todo esto, por si te ayuda mejor a entender este método.

Puesto que estamos dentro de una clase, hay que pasarle el self al método interno, si no lo haces, no podrás referenciar a atributos u otros métodos de la clase.

Después, los dos métodos que quiero decorar, tienen un parámetro, "nombre_db". Lo he puesto como nombre_db, pero no es obligatorio que tenga ese mismo nombre.

Te recomiendo mejor, que pongas *args por si hay que decorar otros métodos con más parámetros:

#Decoradora para el reporte de bases de datos en el servidor
    def reporte_bd(funcion_parametro):
        def interno(self, *args):
            funcion_parametro(self, *args)
            print("Estas son las bases de datos que tiene el servidor:")
            BaseDatos.mostrar_bd(self)
        return interno

Antes de llamar a la función parámetro (línea 4), podría haber incluido algo de código. En este caso, no me hace falta, así que llamo directamente.

Finalmente, saco el print que se repetía y la llamada al método mostrar_bd() para que las muestre.

Quizás te confunda la forma de llamar al método. Esto se hace así debido al alcance. Primero tengo que hacer referencia a la clase con "BaseDatos" (con self, se hace referencia al propio objeto que se instancia, no a la clase). Usando un punto, puedo indicarle qué método quiero llamar de la clase.

Finalmente, el archivo "base_datos.py" debe quedar así. En las líneas 35 y 44 decoro los dos métodos.

import mysql.connector

#conexion con la base de datos
acceso_bd = {"host" : "localhost",
             "user" : "root",
             "password" : "programacionfacil",
             }

class BaseDatos:
    #Conexión y cursor
    def __init__(self, **kwargs):
        self.conector = mysql.connector.connect(**kwargs)
        self.cursor = self.conector.cursor()
    
    #Decoradora para el reporte de bases de datos en el servidor
    def reporte_bd(funcion_parametro):
        def interno(self, nombre_db):
            funcion_parametro(self, nombre_db)
            print("Estas son las bases de datos que tiene el servidor:")
            BaseDatos.mostrar_bd(self)
        return interno
    
    #Consultas SQL    
    def consulta(self, sql):
        self.cursor.execute(sql)
        return self.cursor
    
    #Mostrar bases de datos
    def mostrar_bd(self):
        self.cursor.execute("SHOW DATABASES")
        for bd in self.cursor:
            print(bd)
             
    #Eliminar bases de datos
    @reporte_bd
    def eliminar_bd(self, nombre_bd):
        try:
            self.cursor.execute(f"DROP DATABASE {nombre_bd}")
            print(f"Se eliminó la base de datos {nombre_bd} correctamente.")
        except:
            print(f"Base de datos '{nombre_bd}' no encontrada.")
    
    #Crear bases de datos
    @reporte_bd
    def crear_bd(self, nombre_bd):
        try:
            self.cursor.execute(f"CREATE DATABASE IF NOT EXISTS {nombre_bd}")
            print(f"Se creó la base de datos {nombre_bd} o ya estaba creada.")
        except:
            print(f"Ocurrió un error al intentar crear la base de datos {nombre_bd}.")

Dejamos el capítulo aquí. En el siguiente, te mostraré como crear un método para hacer copias de seguridad de cualquier base de datos MySQL.

No te pierdas nada de todo el contenido que tengo sobre Python.

Un comentario en «Crear aplicación gráfica con Python, MySQL y Tkinter»

  1. Como se podría hacer para que el retorno de la función decoradora
    cambie si la función que recibe como argumento ejecuta try o except?

    Gracias por el curso!!

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

curso de Python Entrada anterior ¿Cómo crear aplicaciones con Python – MySQL y Tkinter?
copias de seguridad mysql Entrada siguiente Copias de seguridad MySQL desde Python