Python - tkinter y sqlite3

 
Vista:
Imágen de perfil de Christian
Val: 11
Ha disminuido su posición en 5 puestos en Python (en relación al último mes)
Gráfica de Python

tkinter y sqlite3

Publicado por Christian (6 intervenciones) el 26/10/2019 23:18:11
Tengo un sencillo programa de experimentación en Python 3 donde utilizo tkinter y sqlite3.

He diseñado una ventana que muestra 4 campos (Código, Apellido, Nombre, Dirección) de una tabla.

He creado, en un frame aparte, 4 botones [<<] [<] [>] [>>]

Lo que deseo y me gustaría que me orienten, es que al pulsar el primer botón ([<<]), en los Entry me muestre los datos del PRIMER registro de la tabla. Al pulsar ([<]) se mueva al registro ANTERIOR (si es que no se encuentra en el primero). Lo mismo con los otros dos botones, sería mover al SIGUIENTE registro, y al ULTIMO registro respectivamente.

En Access, lo puedo hacer con el método .MoveNext .MoveLast etc.

Hay algo parecido en sqlite3 o hay que manejarlo de otra manera?

muchas gracias!
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de joel
Val: 3.475
Oro
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

tkinter y sqlite3

Publicado por joel (901 intervenciones) el 27/10/2019 12:37:43
Hola Christian, podría haber esa manera, si descargas todos los registros y los pones en una variable y luego trabajas sobre la misma, pero no te lo recomiendo...

Lo suyo es que para ver el siguiente registros hagas una consulta a la base de datos para que te lo devuelva, igual para el anterior, inicio y fin.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de algoritmo
Val: 819
Bronce
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

tkinter y sqlite3

Publicado por algoritmo (245 intervenciones) el 27/10/2019 19:39:58
Hola.

Intenta con lo siguiente:

1
2
3
4
5
6
7
import sqlite3
conexion = sqlite3.connect(FICHERO_SQLITE)  # FICHERO_SQLITE es el nombre de tu fichero 
cursor = conexion.cursor()
consulta = "SELECT ......."  # Escribe aquí tu consuta SQL
cursor.execute(consulta)
registros = cursor.fetchall()
conexion.close()

# Los tienes en la variable registros, así:
registros[0] el primero
registros[1] segundo .....

Espero que te sirva :)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de Christian
Val: 11
Ha disminuido su posición en 5 puestos en Python (en relación al último mes)
Gráfica de Python

tkinter y sqlite3

Publicado por Christian (6 intervenciones) el 27/10/2019 23:15:55
Gracias por las respuestas!
Eso mismo tenía hecho pero se me dio por pensar que pudiera existir algún metodo de Sqlite3 que lo facilite un poco.
Pego a continuación lo que tengo realizado (y funciona) por si a alguien se le ocurre mejorarlo un poco:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def LLenaCampos(registro):
 
 for Campo in registro:
           CajaCod.set(Campo[0])
           CajaApe.set(Campo[1])
           CajaNom.set(Campo[2])
           CajaDom.set(Campo[3])
 
def IncrementaReg():
     BaseDatos=sqlite3.connect("Archivo Personas")
     CursorDatos=BaseDatos.cursor()
     RegActual=CajaCod.get()
     RegSig=int(RegActual) + 1
     ClausulaSTR="SELECT * FROM PERSONAS WHERE CODIGO=" + str(RegSig)
     CursorDatos.execute(ClausulaSTR)
     RegitroLeido=CursorDatos.fetchall()
     LLenaCampos(RegitroLeido)
 
def DecrementaReg():
     BaseDatos=sqlite3.connect("Archivo Personas")
     CursorDatos=BaseDatos.cursor()
     RegActual=CajaCod.get()
     RegAnt=int(RegActual) - 1
     ClausulaSTR="SELECT * FROM PERSONAS WHERE CODIGO=" + str(RegAnt)
     CursorDatos.execute(ClausulaSTR)
     RegitroLeido=CursorDatos.fetchall()
     LLenaCampos(RegitroLeido)
 
def IrPrimerRegistro():
     BaseDatos=sqlite3.connect("Archivo Personas")
     CursorDatos=BaseDatos.cursor()
     ClausulaSTR="SELECT * FROM PERSONAS WHERE CODIGO=1"
     CursorDatos.execute(ClausulaSTR)
     RegitroLeido=CursorDatos.fetchall()
     LLenaCampos(RegitroLeido)
 
def IrUltimoRegistro():
     BaseDatos=sqlite3.connect("Archivo Personas")
     CursorDatos=BaseDatos.cursor()
     ClausulaSTR="SELECT COUNT(*) FROM PERSONAS"
     CursorDatos.execute(ClausulaSTR)
     RegitroLeido=CursorDatos.fetchone()
     Ultimo=RegitroLeido[0]
     ClausulaSTR="SELECT * FROM PERSONAS WHERE CODIGO=" + str(Ultimo)
     CursorDatos.execute(ClausulaSTR)
     RegitroLeido=CursorDatos.fetchall()
     LLenaCampos(RegitroLeido)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de Christian
Val: 11
Ha disminuido su posición en 5 puestos en Python (en relación al último mes)
Gráfica de Python

tkinter y sqlite3

Publicado por Christian (6 intervenciones) el 28/10/2019 15:18:07
El problema que tengo con este código es que, por ejemplo, si elimino el anteúltimo registro, ya no me trabaja bien la función IrUltimoRegistro() ya que, supongamos que la tabla tiene guardado hasta el CODIGO 22, pero son 21 registros, y quiero apuntar al registro cuyo código es 22, pero me toma el 21.
Y si justo el 21 fue eliminado, no se puede accesar.
¿Alguna idea?

Gracias!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Christian
Val: 11
Ha disminuido su posición en 5 puestos en Python (en relación al último mes)
Gráfica de Python

tkinter y sqlite3

Publicado por Christian (6 intervenciones) el 29/10/2019 00:33:59
Bueno, dándole vueltas al asunto he logrado "evitar" los registros eliminados, es decir, los "saltos" que quedan en el campo CODIGO tras eliminar un registro.
Tener en cuenta que mi tabla de pruebas tiene los siguientes campos: CODIGO, APELLIDO, NOMBRE, DIRECCION y que las consultas las realizo sobre el campo CODIGO.
Lo que quiero decir es que, estando la tabla completa, como ser CODIGO=1, CODIGO=2, CODIGO=3, CODIGO=4, CODIGO=5 ... CODIGO=23 es fácil moverse, por ejemplo, del 1 al 2, pero si eliminamos el registro correspondiente a CODIGO=2, los datos quedan:
CODIGO=1, CODIGO=3, CODIGO=4, etc. Entonces si le sumo +1 al CODIGO=1, intentando leer el siguiente registo, obtengo un valor nulo y mi algritmo falla.

La solución que encontré es ordenar la tabla antes de realizar la consulta. Para ir al último registro, ordeno la tabla de manera descendente y leo el primer registro (.fetchone) del recordset. Esto me garantiza que me traiga siempre el último, tenga el campo CODIGO el valor que sea, pues el COUNT puede contar 20 registros pero en realidad el último registro (el número 20 del recordset) puede tener el campo CODIGO=23, puesto que en un principio habían 23 registros pero se eliminaron 3. Tal como se encontraba mi algoritmo, cuando pulsaba en el botón [>>] par moverme al último, me visualizaba el CODIGO=20 (porque contaba 20 registros) sin embargo el último registro era CODIGO=23. Utilizando la cláusula ORDER BY sea descendente (DESC) o ascendente (ASC) se soluciona el problema.

En cuanto a incrementar y decrementar al presionar los botones correspondientes de la interface ( [ < ] y [ > ] ), he logrado "saltar" los lugares vacíos pidiendo el LEN del registro leído. Si es 0 (cero), quiere decir que me encontré con un "hueco" en el campo CODIGO, por lo tanto sumo +2 para saltarlo y relizo una nueva consulta.
Se que no es la solución ideal, porque estoy realizando 2 consultas seguidas para una misma operación pero por ahora funciona. Iré viendo cómo lo perfecciono y le agregaré el método close() y demás detalles.

Por el momento pego el código corregido, no sin antes agradecer vuestros comentarios.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
def IncrementaReg(): # Similar a MoveNext de ADO
    BaseDatos=sqlite3.connect("Archivo Personas")
    CursorDatos=BaseDatos.cursor()
    RegActual=CajaCod.get()
    RegSig=int(RegActual) + 1
    ClausulaSQL="SELECT * FROM PERSONAS WHERE CODIGO=" + str(RegSig)
    CursorDatos.execute(ClausulaSQL)
    RegistroLeido=CursorDatos.fetchall()
    if len(RegistroLeido) == 0:
        RegSig=int(RegActual) + 2
        ClausulaSQL="SELECT * FROM PERSONAS WHERE CODIGO=" + str(RegSig)
        CursorDatos.execute(ClausulaSQL)
        RegistroLeido=CursorDatos.fetchall()
    LLenaCampos(RegistroLeido)
 
def DecrementaReg(): # Similar a MovePrevious de ADO
    BaseDatos=sqlite3.connect("Archivo Personas")
    CursorDatos=BaseDatos.cursor()
    RegActual=CajaCod.get()
    RegAnt=int(RegActual) - 1
    ClausulaSQL="SELECT * FROM PERSONAS WHERE CODIGO=" + str(RegAnt)
    CursorDatos.execute(ClausulaSQL)
    RegistroLeido=CursorDatos.fetchall()
    if len(RegistroLeido) == 0:
        RegSig=int(RegActual) - 2
        ClausulaSQL="SELECT * FROM PERSONAS WHERE CODIGO=" + str(RegSig)
        CursorDatos.execute(ClausulaSQL)
        RegistroLeido=CursorDatos.fetchall()
    LLenaCampos(RegistroLeido)
 
def IrPrimerRegistro(): # Similar a MoveFirst de ADO
    BaseDatos=sqlite3.connect("Archivo Personas")
    CursorDatos=BaseDatos.cursor()
    # ordeno ascendente la tabla por código y levanto el primer registro
    ClausulaSQL="SELECT * FROM PERSONAS ORDER BY CODIGO ASC LIMIT 1"
    CursorDatos.execute(ClausulaSQL)
    RegistroLeido=CursorDatos.fetchall()
    LLenaCampos(RegistroLeido)
 
def IrUltimoRegistro(): # Similar a MoveLast de ADO
    BaseDatos=sqlite3.connect("Archivo Personas")
    CursorDatos=BaseDatos.cursor()
    # ordeno descendente la tabla por CODIGO y levanto el primer registro (obteniendo el último)
    ClausulaSQL="SELECT * FROM PERSONAS ORDER BY CODIGO DESC LIMIT 1"
    CursorDatos.execute(ClausulaSQL)
    RegistroLeido=CursorDatos.fetchall()
    LLenaCampos(RegistroLeido)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de algoritmo
Val: 819
Bronce
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

tkinter y sqlite3

Publicado por algoritmo (245 intervenciones) el 28/10/2019 16:03:51
Hola

Confío en que el siguiente código te de alguna idea. ¡Ojo!, no lo tengo probado, puede tener errores.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
def lee_registros():
    import sqlite3
    conexion = sqlite3.connect("Archivo Personas")
    cursor = conexion.cursor()
    consulta = "SELECT * FROM PERSONAS ORDER BY CODIGO"
    cursor.execute(consulta)
    reg = cursor.fetchall()
    conexion.close()
    return reg
 
def IrPrimerRegistro():
    puntero = 1
    return registros[0]
 
def IrUltimoRegistro():
    puntero = registros.count()
    return registros[-1]
 
def IncrementaReg():
    puntero += 1
    if puntero > len(registros):
        puntero = len(registros)
    return registros[puntero-1]
 
def DecrementaReg():
    puntero -= 1
    if puntero < 1:
        puntero = 1
    return registros[puntero-1]
 
registros = lee_registros()
puntero = 1
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de algoritmo
Val: 819
Bronce
Ha mantenido su posición en Python (en relación al último mes)
Gráfica de Python

tkinter y sqlite3

Publicado por algoritmo (245 intervenciones) el 28/10/2019 17:38:16
Corrigiéndome


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
def lee_registros():
    import sqlite3
    conexion = sqlite3.connect("Archivo Personas")
    cursor = conexion.cursor()
    consulta = "SELECT * FROM PERSONAS ORDER BY CODIGO"
    cursor.execute(consulta)
    reg = cursor.fetchall()
    conexion.close()
    return reg
 
def IrPrimerRegistro():
    global puntero
    puntero = 1
    return registros[0]
 
def IrUltimoRegistro():
    global puntero
    puntero = len(registros)
    return registros[-1]
 
def IncrementaReg():
    global puntero
    puntero += 1
    if puntero > len(registros):
        puntero = len(registros)
    return registros[puntero-1]
 
def DecrementaReg():
    global puntero
    puntero -= 1
    if puntero < 1:
        puntero = 1
    return registros[puntero-1]
 
registros = lee_registros()
puntero = 1
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de Christian
Val: 11
Ha disminuido su posición en 5 puestos en Python (en relación al último mes)
Gráfica de Python

tkinter y sqlite3

Publicado por Christian (6 intervenciones) el 28/10/2019 18:26:04
Nuevamente gracias por prestar atención a mis dudas de principiante.
Voy a probar tu ejemplo, pero a simple vista observo que metes todos los registros en memoria.
Para una tabla de 1000 registros no hay demasiado problema, pero si se trata de tablas realmente grandes vinculadas con otras?
Saludos!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar