Aplicacion grafica con pyqt4 y sqlite3 en python

pyqt4 y sqlite3
Conexión pyqt4 y sqlite3

En la entrada anterior estuvimos viendo como crear una aplicación en Qt Designer y Python. También deje unos ejercicios para practicar con las aplicaciones gráficas.
Hoy la idea es crear una sencilla aplicación gráfica (también utilizando pyqt4 y python) y conectar dicha aplicación a una base de datos sqlite3 para que nuestros datos sean guardados y recuperados.

Funcionalidad de la aplicación:

En la
aplicación se podrán guardar los datos de los clientes (Nombre, Apellido y
Localidad). El cliente será guardado en una base de datos al presionar
el botón Guardar.
Para ver todos los clientes almacenados en nuestra base de datos presionamos el botón Cargar.

 

Componentes de la aplicación:

Abrimos QtDesigner y creamos un nuevo Main Window. Tratar de dejarlo lo más parecido a la siguiente imagen:

Componentes de la aplicación
Componentes de la aplicación

4 - Etiquetas (Clientes, Nombre, Apellido, Localidad)
3 - LineEdit
2 - Botones (Guardar y Cargar)
1 - List Widget

ObjectName de los componentes:

Son los nombres con los que haremos referencia en el código

LineEdit - (lineEdit, lineEdit_2, lineEdit_3)
Botones - (btn_Guardar, btn_Cargar)
List Widget - (lista)

Guardamos el archivo con el nombre: conBase.ui

Creamos un nuevo archivo conBase.py en el IDE que nos guste más (tiene que estar en el mismo directorio que conBase.ui) y codeamos lo siguiente:

Código de la aplicación:

#!/usr/bin/python
# -*- coding: utf-8 -*-

# Aplicacion grafica con sqlite3
# www.pythondiario.com
 
import sys
import sqlite3
from PyQt4 import QtCore, QtGui, uic

# Cargar nuestro archivo .ui
form_class = uic.loadUiType("conBase.ui")[0]

class MyWindowClass(QtGui.QMainWindow, form_class):
 def __init__(self, parent=None):
  QtGui.QMainWindow.__init__(self, parent)
  self.setupUi(self)
  self.btn_Guardar.clicked.connect(self.btn_Guardar_clicked)
  self.btn_Cargar.clicked.connect(self.btn_Cargar_clicked)
  self.IniciarBase()
  

 def IniciarBase(self):
  self.con = sqlite3.connect("/home/diego123/Escritorio/pyqt4/prueba.bd")
  self.cursor = self.con.cursor()
  self.cursor.execute ("""CREATE TABLE IF NOT EXISTS campos(NOMBRE TEXT NOT NULL, APELLIDO TEXT NOT NULL, LOCALIDAD TEXT NOT NULL)""" )
  self.con.commit()

 # Evento del boton Guardar
 def btn_Guardar_clicked(self):

  self.con = sqlite3.connect("/home/diego123/Escritorio/pyqt4/prueba.bd")
  self.cursor = self.con.cursor()

  # Datos
  self.nombre = str(self.lineEdit.text())
  self.apellido = str(self.lineEdit_2.text())
  self.localidad = str(self.lineEdit_3.text())
  self.datos = (self.nombre, self.apellido, self.localidad)

  # Inserta los datos en la tabla campos
  self.cursor.execute("INSERT INTO campos (nombre, apellido, localidad) VALUES (?,?,?)", self.datos)
  self.con.commit()

  # Quedan los campos vacios al guardar cliente
  self.lineEdit.setText("")
  self.lineEdit_2.setText("")
  self.lineEdit_3.setText("")

  self.con.commit()
  self.con.close()

 # Evento del boton Caragar
 def btn_Cargar_clicked(self):

  self.con = sqlite3.connect("/home/diego123/Escritorio/pyqt4/prueba.bd")
  self.cursor = self.con.cursor()
  
  # Se cargan los datos indicados de la tabla
  self.cursor.execute("SELECT NOMBRE, APELLIDO, LOCALIDAD FROM campos")

  # Al presionar el boton lo primero es borrar todos los datos
  self.lista.clear()

  # Se agregan los elementos al QListWidget
  for i in self.cursor:
   self.nombre = str(i[0])
   self.apellido = str(i[1])
   self.localidad = str(i[2]) 
   
   self.lista.addItem(self.nombre + " - " + self.apellido + " - " + self.localidad)

  self.con.commit()
  self.con.close()
   
 
app = QtGui.QApplication(sys.argv)
MyWindow = MyWindowClass(None)
MyWindow.show()
app.exec_()

Análisis del código:

En la parte superior importamos la biblioteca PyQt, sqlite3 y cargamos el archivo conBase.ui que generamos anteriormente con QtDesigner.

Creamos la clase MyWindowClass y le pasamos (QtGui.QMainWindow y
form_class). El método __init__ configura la interfaz GUI. En esta
función tenemos que conectar los controladores de eventos:

self.btn_Guardar.clicked.connect(self.btn_Guardar_clicked)
self.btn_Cargar.clicked.connect(self.btn_Cargar_clicked)
self.IniciarBase()

El método clicked.connect es llamado cuando el botón es presionado.


Funciones de nuestra aplicación:

def IniciarBase(self):
  self.con = sqlite3.connect("/home/diego123/Escritorio/pyqt4/prueba.bd")
  self.cursor = self.con.cursor()
  self.cursor.execute ("""CREATE TABLE IF NOT EXISTS campos(NOMBRE TEXT NOT NULL, APELLIDO TEXT NOT NULL, LOCALIDAD TEXT NOT NULL)""" )
  self.con.commit()

La función IniciarBase(), como su nombre lo indica, inicia la base de datos de nuestra aplicación, y es colocada en el método __init__ para que se inicie cuando ejecutemos nuestro programa.
Si no existe, se crea la tabla campos con 3 elementos (NOMBRE, APELLIDO, LOCALIDAD).
Si no sabes como funciona una base de datos Sqlite3 en python, te recomiendo que mires la siguiente entrada: Sqlite3 y Python

# Evento del boton Guardar
 def btn_Guardar_clicked(self):

  self.con = sqlite3.connect("/home/diego123/Escritorio/pyqt4/prueba.bd")
  self.cursor = self.con.cursor()

  # Datos
  self.nombre = str(self.lineEdit.text())
  self.apellido = str(self.lineEdit_2.text())
  self.localidad = str(self.lineEdit_3.text())
  self.datos = (self.nombre, self.apellido, self.localidad)

  # Inserta los datos en la tabla campos
  self.cursor.execute("INSERT INTO campos (nombre, apellido, localidad) VALUES (?,?,?)", self.datos)
  self.con.commit()

  # Quedan los campos vacios al guardar cliente
  self.lineEdit.setText("")
  self.lineEdit_2.setText("")
  self.lineEdit_3.setText("")

  self.con.commit()
  self.con.close()

La función btn_Guardar_clicked(self), se encargará de guardar los datos del cliente en nuestra tabla campos. Al presionar guardar se borran los contenidos de los lineEdit para llenar otro cliente.

# Evento del boton Caragar
 def btn_Cargar_clicked(self):

  self.con = sqlite3.connect("/home/diego123/Escritorio/pyqt4/prueba.bd")
  self.cursor = self.con.cursor()
  
  # Se cargan los datos indicados de la tabla
  self.cursor.execute("SELECT NOMBRE, APELLIDO, LOCALIDAD FROM campos")

  # Al presionar el boton lo primero es borrar todos los datos
  self.lista.clear()

  # Se agregan los elementos al QListWidget
  for i in self.cursor:
   self.nombre = str(i[0])
   self.apellido = str(i[1])
   self.localidad = str(i[2]) 
   
   self.lista.addItem(self.nombre + " - " + self.apellido + " - " + self.localidad)

  self.con.commit()
  self.con.close()

La función btn_Cargar_clicked(self), se encargará de mostrar en el List Widget, todos los clientes que hallamos ingresado.

Al final del código, necesitamos iniciar la interfaz gráfica:

app = QtGui.QApplication(sys.argv)
MyWindow = MyWindowClass(None)
MyWindow.show()
app.exec_()  

Espero que esta entrada les sea de ayuda para sus futuras aplicaciones en python. Saludos

  1. Anónimo dice:

    Felicidades, lo ejecute y salio OK

    1. PythonDiario dice:

      Excelente 🙂 . Saludos

  2. Anónimo dice:

    Excelente! para empezar a crear proyectos... Diego, me gustarìa que compartieras un metodo de PyQt para importar imagenes, es decir asignar una foto a cada ID en la base de datos! Agradecerìa la ayuda ya que la documentacion de QT esta en ingles :/ mi email es wwizka@hotmail.com

    1. PythonDiario dice:

      Hola, estuve buscando algo de información sobre como guardar imágenes en una base de datos Sqlite y encontré algunas discusiones sobre si es bueno o no guardar directamente las imágenes en la base de datos (se hace muy pesada). Algunos recomiendan usar Postgres que viene con un tipo de datos para las fotos. Otros recomiendan guardar las imágenes en una carpeta y en la base de datos guardar la ruta de dicha imagen.
      Quizá más adelante cree una entrada sobre este tema.
      Saludos

  3. Unknown dice:

    disculpa amigo estoy programando con python y me encontre con un problema me pide el modulo dockwidgets_rc

    y la verdad no lo encuentro

  4. Unknown dice:

    Hola me gustaria saber como conectar con una base de datos en mysql y phpmyadmin gracias estoy empezando en la programacion

  5. Anónimo dice:

    Me parece interesante... Ahora cómo haría para actualizar un dato o en su caso, eliminarlo?

    1. PythonDiario dice:

      Hola, ya voy a realizar una entrada con modificación y eliminación. Saludos y gracias por visitar el blog.

    2. Unknown dice:

      Hola Diego! Soy Lucas. Primero queria felicitarte por el excelente laburo de la web. Tengo un par de dudas:
      1- A este mismo scrip le quiero agregar como mencionas la parte de modificacion y eliminacion.

      2- Como hago para ejecutar este programa sin hacerlo desde la consola?

      Gracias!

    3. PythonDiario dice:

      Hola Lucas, como estas? Gracias por visitar el blog. Todavía no he realizado el ABM completo de la aplicación. Ni bien me haga un tiempito agrego como eliminar y como modificar. Para la segunda pregunta, ¿Qué sistema operativo utilizas?
      Saludos!!!

    4. Unknown dice:

      Como estas Diego? Estoy usando Ubuntu Mate 16.04, desde la consola lo ejecuto con "python ******.pyc". Con respecto a lo de modificar o actualizar y eliminar, tome tu codigo como referencia pero me saltan algunos errores. Saludos!

    5. PythonDiario dice:

      Hola Gallito, todo bien por acá, tu? Cual es el error que te sale?
      Saludos!!!

    6. Unknown dice:

      Todo bien Diego! Te puedo pasar el archivo .py o te copio el código de lo que tengo hasta ahora?

  6. Unknown dice:

    Una pregunta a mi me da este error, como que no puede importar las librerias

    Traceback (most recent call last):
    File "C:/base/conBase.py", line 9, in
    from PyQt4 import QtCore, QtGui, uic
    ImportError: No module named PyQt4

  7. Unknown dice:

    Hola, ya lo solucione en Windows era la versión de PyQt4.
    ahora tengo otro problema estoy en linux y me da este error. Me puedes ayudar? gracias

    Traceback (most recent call last):
    File "conBase.py", line 8, in
    class MyWindowClass(QtGui.QMainWindow, form_class):
    File "conBase.py", line 47, in MyWindowClass
    for i in self.cursor:
    NameError: name 'self' is not defined

    1. PythonDiario dice:

      Hola Marcelo, fijate que lo tengas bien instaldo, debe venir por ahí la mano: https://www.pythondiario.com/2013/11/como-instalar-pyqt4-en-windows-linux-y.html

      Saludos y gracias por visitar el blog.

    2. Hugo A. Guerrero G. dice:

      Marcelo Bazan, no se si sea muy tarde pero para corregir "NameError: name 'self' is not defined" fíjate que estés respetando las indentaciones, en Python son muy importantes.

  8. Unknown dice:

    Hola Diego espero estes bien. me surgió una duda, en el siguiente código:

    self.con = sqlite3.connect("/home/diego123/Escritorio/pyqt4/prueba.bd")

    Me preguntaba de dónde obtuviste la ruta.
    En mi caso como yo tenia los archivos junto con la base de datos, solo puse:

    self.con = sqlite3.connect("base.bd")

    y me lanzó este error:

    File "C:UsersUsuario1DocumentsPRACTICASprograma de contactos con dbconBase.py", line 15, in IniciarBase
    self.con = sqlite3.connect("base.db")
    RuntimeError: maximum recursion depth exceeded while calling a Python object

    ¿Cómo podrías solucionarlo?

    Espero puedas apoyarme, gracias Diego.

    1. Unknown dice:

      self.con = sqlite3.connect("./prueba.bd")

    2. Unknown dice:

      perdón, en tu caso:
      self.con = sqlite3.connect("./base.bd")

  9. Anónimo dice:

    Amigo como podría hacer si quisiera por ejemplo eliminar datos agregados a la tabla desde la interfaz y no solo dentro del codigo?

  10. Unknown dice:

    Este comentario ha sido eliminado por el autor.

  11. Unknown dice:

    Muy buen tut! Siempre he hecho interfaces como éstas pero sólo con Tkinter; sin embargo, tenía el problema que no quedaban buen distribuidos los widgets con pack y grid. Ahora creo que con este tut se mejoran las cosas.
    Por cierto, también me gustaría saber como sería si quisiera botones para editar y borrar los registros, y además de trabajarlos en sqlite, cómo sería con Mysql, que sería mucho más seguro para mí.

  12. Unknown dice:

    Hola, muy buena entrada, pero hay algo que no entiendo. Después de borrar los lineEdit haces un commit a la base de datos, ¿con que finalidad? Saludos

    1. crostow dice:

      segun tengo entendido el commit es para hacer efectiva la escritura de los datos en la bd

  13. crostow dice:

    saludos pido su ayuda si alguien sabe como puedo obtener la posicion de una celda de un qtablewidget seleccionandola espero haberme dado a entender

    1. PythonDiario dice:

      Hola crostow, quizá puedas revisar bien en la documentación oficial: http://pyqt.sourceforge.net/Docs/PyQt4/qtablewidget.html, Saludos y gracias por visitar el blog.

    2. crostow dice:

      ok solucionado gracias por la informacion
      por cierto realize un pequeño punto de venta muy basico

      alta, modificacion , elimimacion de productos y usuarios y un pequeño corte con los productos vendido por dia

      me gustaria compartirlo como se haria bueno se se puede

    3. PythonDiario dice:

      Hola crostow, exclente. Puedes enviarme el código a la dirección: diegocaraballo84@gmail.com, con algún comentario y puedo agregarlo como una entrada, puedes pasarme tus datos de contacto para agregar tus créditos. Saludos y gracias por visitar el blog 😉

  14. Hugo A. Guerrero G. dice:

    Hola crostow, también estoy interesado ver como armaste el proyecto, o por lo menos una parte de el, agradecido por el aporte.
    Mi dirección es: hugoguerrero03@gmail.com.

    1. crostow dice:

      ya mande el codigo solo falta que lo agreguen

    2. PythonDiario dice:

      Excelente, esta semana lo bajo, reviso el código y lo subo. Gracias por el aporte 😉
      Saludos, Diego.

    3. crostow dice:

      bueno ya subi el proyecto a git hub si aun les interesa esta es la direccion

      https://github.com/crostow/punto-de-venta

    4. PythonDiario dice:

      Hola, disculpa que no he podido publicar una entrada sobre tu app, he estado medio corto de tiempo. En cuanto me haga un tiempito la analizo bien y la subo. Gracias 😉

  15. Blog de Francisco y Angel dice:

    Hola que tal tengo este problema
    Espero alguien me pueda decir que es lo que estoy haciendo mal
    Al momento de ejecutar el codigo me aparece un error
    Traceback (most recent call last):
    File "C:/Proyecto/ConversionesTemp/conBase1.py", line 63, in btn_Cargar_clicked
    self.lista.clear()
    AttributeError: 'MyWindowClass' object has no attribute 'lista'
    Ese es el error que me aparece cuando doy click en el boton cargar

    1. PythonDiario dice:

      Hola, fijate que en QtDesigner hallas cambiado el nombre del List Widget a Lista. Saludos

  16. KiwexTV dice:

    saludos tendras el codigo para eliminar datos de lista ? y crear un boton que conduzca a otra ventana o a otro .ui gracias

    1. PythonDiario dice:

      Hola Alejandro, perdón la demora. Al momento no tengo nada de lo que pides. Ya crearé un ABM (ALTA, BAJA, MODIFICACIÓN). Saludos

  17. Steve dice:

    Hola, para conectar con postgress puedo usar el mismo codigo? solo cambio la conexion?

    1. PythonDiario dice:

      Hola Marcos, además de la conexión, cambias las consultas (por ejemplo en insert). Fijate en la documentación oficial de Postgres. Saludos

  18. Anónimo dice:

    Hola Daniel,

    Excelente gracias, podrías hacer algo parecido pero con wxpython (sqlite + wxpython).

    Saludos!

  19. Unknown dice:

    Este comentario ha sido eliminado por el autor.

  20. Unknown dice:

    Hola diego buenos dias, estari teniendo este problema, como lo podria solucionar:
    File "C:UsersLautaro BustosDesktopconbase.py", line 9, in
    from PyQt4 import QtCore, QtGui, uic
    ImportError: DLL load failed: %1 no es una aplicaci¾n Win32 vßlida.

    Gracias de ante mano

  21. PythonDiario dice:

    Hola Lautaro, como estas?
    Reinstalar PyQt4, Esto sucede a menudo debido a un problema con la instalación

  22. Unknown dice:

    Perdon Diego que moleste denuevo pero ya pude instalar PyQt 4 reinstalandolo como vos me dijiste, gracias. Ahora quiero aprender a usar este modulo. Porque al principio del codigo declaras esto: form_class = uic.loadUiType("conBase.ui")[0] . Que significa "[0]" ?
    Muchas gracias, saludos.

  23. Unknown dice:

    Hola,
    Tengo un problema parecido: podría sustituir tu "list Widget" por un "TableView"?....cómo habría que hacer el código en python?
    Gracias

  24. Juan Barraza dice:

    Excelente aporte, no encontraba respuesta en ningún lado y tu me diste la solución... gracias amigo.

Deja una respuesta

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

Subir

Te has suscrito correctamente al boletín

Se produjo un error al intentar enviar tu solicitud. Inténtalo de nuevo.

Mi Diario Python will use the information you provide on this form to be in touch with you and to provide updates and marketing.