Forum >> Programmazione Python >> Database >> PY

Pagina: Indietro 1 2 3 Avanti

.
--- Ultima modifica di Nino48 in data 2022-11-17 14:19:09 ---
Daniele aka Palmux said @ 2022-11-15 19:27:05:
.
--- Ultima modifica di Nino48 in data 2022-11-17 14:19:24 ---
Si vorrei vederlo grazie mille
Mi scuso se incollo qui il codice pur essendo lungo, non conosco pastebin, mi sembra voglia il login.

Il codice che segue e di tipo "funzionale" (le mie considerazioni sul pattern le ho già espresse) ed opera con sqlite3, provvedendo a creare una tavola come indicato nel 1° post di @nino48 e crea una finestra con tre entry per l'inserimento dei dati (il widget tk.Text è eccessivo per lo sscopo), verifica che i dati siano completi e permette di inserirli e sfogliarli ma non di modificarli o cancellarli.

Ho staccato la logica di callback dalla logica di manipolazione dati, i callback sono effettuati da specifiche funzioni (on_new, on_undo, on_save, on_previous, on_next ed on_close) valorizzando il parametro "command" dei pulsanti di controllo.

Le funzioni di manipolazione e ricerca dati (connect, make_table e get_data) e per la visualizzazione (on_index e show_data) fanno riferimento a variabili globali, in particolare la connessione al database si effettua una sola volta ed riutilizzata per tutta la durata applicativa, i cursori vengono, invece, definiti alla bisogna all'interno delle funzioni di gestione.
Il database (tab1.db) viene posizionato nella directory dello script, si faccia molta attenzione all'ordine di definizione delle variabili ed implementazione delle funzioni, una funzione NON vede le variabili globali definite dopo di essa.
Si faccia attenzione che a volte l'editor modifica il codice (non so come manipolarlo per correggere)
import os
import sys
import sqlite3

import tkinter as tk
from tkinter import messagebox

def make_table(conn):
    query =  'CREATE TABLE two (name TEXT, age INTEGER, height REAL)'
    curr = conn.cursor()
    curr.execute(query)

def get_data(conn):
    query = 'SELECT * FROM two'
    try:
        curr = conn.cursor()
        result = curr.execute(query).fetchall()
    except:
        return None
    return result
    
def store_new(conn, new_data):
    query = 'INSERT INTO two VALUES(?, ?, ?)'
    try:
        cur = conn.cursor()
        cur.execute(query, new_data)
        conn.commit()
    except Exception as e:
        conn.rollback()
        raise Exception(e)

def connect():
    app_dir = os.path.abspath(os.path.dirname(sys.argv[0]))
    dbname = os.path.join(app_dir, 'Tab1.db')
    nodb = False
    if not os.path.exists(dbname) or not os.path.isfile(dbname):
        nodb = True
    try:
        conn = sqlite3.connect(dbname)
        if nodb: make_table(conn)
    except:
        return None
    return conn

conn = connect()
data = None
index = 0

window = tk.Tk()
window.title('server')
window.resizable(True, False)
dida =  tk.Label(window, text='')
dida.grid(row=0, column=0, columnspan=2, padx=5, pady=5, sticky='w')
lbl = tk.Label(window, text='Nome :')
lbl.grid(row=1, column=0, padx=5, pady=5, sticky='w')
text_box_1 = tk.Entry(window)
text_box_1.grid(row=1, column=1, padx=5, pady=5, sticky='ew')
lbl = tk.Label(window, text='Età :')
lbl.grid(row=2, column=0, padx=5, pady=5, sticky='w')
text_box_2 = tk.Entry(window, width=5)
text_box_2.grid(row=2, column=1, padx=5, pady=5, sticky='w')
lbl = tk.Label(window, text='Altezza :')
lbl.grid(row=3, column=0, padx=5, pady=5, sticky='w')
text_box_3 = tk.Entry(window, width=7)
text_box_3.grid(row=3, column=1, padx=5, pady=5, sticky='w')

cmd = []

def show_data():
    if not data:
        dida.configure(text='Nessun dato esistente')
        messagebox.showinfo('Informazione', 'Nessun dato disponibile')
        return
    dida.configure(text='Record %d di %d' % (index+1, len(data)))
    dida.update()
    row = data[index]
    text_box_1.delete(0, 'end')
    text_box_2.delete(0, 'end')
    text_box_3.delete(0, 'end')
    text_box_1.insert('end', row[0])
    text_box_2.insert('end', str(row[1]))
    text_box_3.insert('end', str(row[2]))
    window.update()

def on_index(value):
    global index
    if not data: return
    index += value
    if index < 0:
        index = len(data) - 1
    elif index >= len(data):
        index = 0
    show_data()

def on_save():
    global data
    name = text_box_1.get()
    age = text_box_2.get()
    height = text_box_3.get()
    if not name or not age or not height:
        msg = 'Completare i dati da inserire'
        messagebox.showwarning('Dati insufficienti', msg)
        return
    try:
        new_data = (name, int(age), float(height))
    except ValueError:
        msg = 'Inserire stringa per il nome, intero per età e float per altezza'
        messagebox.showerror('Dati non validi', msg)
    try:
        store_new(conn, new_data)
    except Exception as e:
        msg = 'Avvenuto errore :\n' + repr(e)
        messagebox.showerror('Errore dati', msg)
        return
    data = get_data(conn)
    cmd[0].configure(state='normal')
    cmd[1].configure(state='disabled')
    cmd[2].configure(state='disabled')
    cmd[3].configure(state='normal')
    cmd[4].configure(state='normal')
    cmd[5].configure(state='normal')
    data = get_data(conn)
    on_index(0)

def on_new():
    text_box_1.delete(0, 'end')
    text_box_2.delete(0, 'end')
    text_box_3.delete(0, 'end')
    cmd[0].configure(state='disabled')
    cmd[1].configure(state='normal')
    cmd[2].configure(state='normal')
    cmd[3].configure(state='disabled')
    cmd[4].configure(state='disabled')
    cmd[5].configure(state='disabled')

def on_previous():
    on_index(-1)

def on_next():
    on_index(1)

def on_undo():
    cmd[0].configure(state='normal')
    cmd[1].configure(state='disabled')
    cmd[2].configure(state='disabled')
    cmd[3].configure(state='normal')
    cmd[4].configure(state='normal')
    cmd[5].configure(state='normal')
    show_data()

def on_close():
    conn.close()
    window.destroy()

pnl = tk.Frame(window)
pnl.grid(row=4, column=0, columnspan=2, sticky='ew')
cmd_new = tk.Button(pnl, text='Nuovo', state='normal', command=on_new)
cmd_new.grid(row=0, column=0, padx=5, pady=5, sticky='ew')
cmd_undo = tk.Button(pnl, text='Annulla', command=on_undo, state='disabled')
cmd_undo.grid(row=0, column=1, padx=5, pady=5, sticky='ew')
cmd_save = tk.Button(pnl, text='Salva', command=on_save, state='disabled')
cmd_save.grid(row=0, column=2, padx=5, pady=5, sticky='ew')
cmd_pre = tk.Button(pnl, text='<', command=on_previous, state='normal')
cmd_pre.grid(row=0, column=3, padx=5, pady=5, sticky='ew')
cmd_next = tk.Button(pnl, text='>', command=on_next, state='normal')
cmd_next.grid(row=0, column=4, padx=5, pady=5, sticky='ew')
cmd_close = tk.Button(pnl, text='Esci', command=on_close, state='normal')
cmd_close.grid(row=0, column=5, padx=5, pady=5, sticky='ew')
cmd += [cmd_new, cmd_undo, cmd_save, cmd_pre, cmd_next, cmd_close]
for i in range(6):
    pnl.grid_columnconfigure(i, weight=1, uniform='a')
window.grid_columnconfigure(1, weight=1)

data = get_data(conn)
show_data()

window.mainloop()
Spero che l'esempio aiuti @nino48, ovviamente come linea logica, fai sapere e per chiarimenti si è qua
EDIT : come temevo, non vengono visualizzate le parntesi quadre alla variabile cmd ed altro, @nino48, tieni presente che cmd è una lista contenente i pulsanti di comendo.


RI-EDIT : inseriti i backslash (ci ho dovuto lavorare un po'), giacché c'ero ho rimediato ad una improprietà formale commessa lasciando l'inserimento dei nuovi dati nel callback, ora è la funzione "store_new(conn, new_data)" quella che effettua l'effettivo inserimento mentre il callback si limita a preparare i dati ed invocarla ... giusto per una più giusta rappresentazione del "model"



--- Ultima modifica di nuzzopippo in data 2022-11-16 11:18:22 ---

--- Ultima modifica di nuzzopippo in data 2022-11-16 14:55:46 ---

--- Ultima modifica di nuzzopippo in data 2022-11-16 14:58:28 ---

--- Ultima modifica di nuzzopippo in data 2022-11-16 15:01:02 ---
Fatti non foste a viver come bruti...
EDIT : come temevo, non vengono visualizzate le parntesi quadre alla variabile cmd ed altro, @nino48, tieni presente che cmd è una lista contenente i pulsanti di comendo.

Ciao caro, metti un \ (back slash) davanti alla parentesi quadra e vedrai che verrà visualizzata.

Stessa cosa per i CamelCase.

Cya
--- Ultima modifica di Nino48 in data 2022-11-17 14:20:14 ---
scusa se ti disturbo ma potresti mettermi un #con commento nello script perche ci sono alcuni comandi che non ho capito cosa fanno all'interno del programma...come alcuni def, pnl e cmd ecc
Eeeeeeeh... insomma... non lo trovo molto corretto. Credo che potresti/dovresti prendere spunto ed approfondire quanto ti ha elargito nuzzopippo.

Vedi questa è esattamente la mia paura di cui scrivevo sopra. Quando si "regala" codice si tende poi a riceverlo senza fare troppa fatica per imparare. Resto contrario a fornire questo tipo di aiuto, perché alla fine non so mai quanto l'utente capisca, oltre a come fare copia ed incolla.

Ringrazio comunque nuzzopippo per la condivisione, ed esorto Nino48 a fare un piccolo (o tanti piccoli) passo in avanti e provare a capire le varie funzionalità proposte.

Ora me ne sto zitto e non rompo più sull'argomento.

Cya
Daniele aka Palmux said @ 2022-11-17 10:35:24:
...Vedi questa è esattamente la mia paura di cui scrivevo sopra. Quando si "regala" codice si tende poi a riceverlo senza fare troppa fatica per imparare. Resto contrario a fornire questo tipo di aiuto, perché ...
In effetti non mi aspettavo una richiesta come quella ricevuta dallo OP, domande a livello così basso da far pensare sconosciuti i concetti di definizione di funzione o nomi di variabili (i cmd_etc) scambiati per chissà che ...

Come hai ben detto, @Palmux, il mio voleva essere solo uno spunto per mostrare una semplice possibile logica di approccio per la evidente carenza operativa che credo di rilevare nel suo primo post ... di per se non sono molto contrario a fornire esempi di codice, spesso io stesso ho i concetti necessari ma non vedo bene come applicarli; ho imparato molto da codice altrui.




@Nino48, mi spiace davvero doverTi dire di no ma per spiegarTi dettagliatamente quel codice dovrei scrivere un mezzo libro in commenti ed avevo detto già prima di postarlo che è troppo lungo.

Debbo, inoltre, dire che sono un po' preoccupato riguardo le scadenze del Tuo stage, se davvero hai problemi sul "def" (che è il punto di inizio della definizione di una funzione o di un metodo) e confondi nomi di variabili quali "cmd" (usato per una lista e per i nomi dei bottoni) con chissà che, significa che hai bisogno di almeno qualche mese di studio prima di poter affrontare argomenti quali le interfacce grafiche (che che se ne pensi la loro implementazione "seria" è MOLTO complessa) e database

... se sei in tale condizione e davvero Ti interessa imparare a programmare in python Ti suggerirei di inzziare con il tutorial e qualche libro elementare (ne trovi i link nella sezione "documentazione" della pagina principale) e solo dopo aver acquisito la bare ri-affrontare l'argomento.




Ciao

Fatti non foste a viver come bruti...
Daniele aka Palmux said @ 2022-11-17 10:35:24:
.
--- Ultima modifica di Nino48 in data 2022-11-17 14:20:30 ---
Daniele aka Palmux said @ 2022-11-17 10:35:24:
.
--- Ultima modifica di Nino48 in data 2022-11-17 14:20:41 ---
Daniele aka Palmux said @ 2022-11-17 10:35:24:
.
--- Ultima modifica di Nino48 in data 2022-11-17 14:20:51 ---


Pagina: Indietro 1 2 3 Avanti



Esegui il login per scrivere una risposta.