IT rekvalifikace s garancí práce. Seniorní programátoři vydělávají až 160 000 Kč/měsíc a rekvalifikace je prvním krokem. Zjisti, jak na to!
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

5. diel - Uloženie objektov do CSV v Pythone časť 2

V minulej lekcii, Uloženie objektov do CSV v Pythone , sme načal databázu užívateľov pomocou CSV súborov. Teraz aplikáciu dokončíme a doladíme.

Načítanie používateľov z CSV súboru

Uloženie nám funguje, zostáva vedieť dáta opätovne načítať. Načítame všetky riadky zo súboru a každý riadok rozdelíme metódou split() a následne do zoznamu pridáme objekt s príslušnými hodnotami. Pred načítaním si zoznam vyprázdnime, aby v ňom neboli aj užívatelia načítanie niekedy skôr (keby sa aplikácia niekedy rozširovala).

def nacti(self):
    self.uzivatele = []
    with open(self.soubor, "r", encoding="utf-8") as f:
        for s in f.readlines():
            jmeno, vek, registrovan = s.strip().split(";")
            registrovan = datetime.datetime.strptime(registrovan, "%d.%m.%Y")
            self.pridejUzivatele(jmeno, vek, registrovan)

Trieda Databaze je teda kompletná. Teraz sa zameriame na formulárovom časť.

Prezentačná vrstva aplikácie

Ako prvý si pripravíme nové formulárové prvky. Aplikácia je napísaná v tkinter, ktorý je už súčasť Pythone. Na vytvorenie formulára som použil pygubu-designer, ktorý nainštalujete pomocou pip install pygubu a spustíte príkazom pygubu-designer. V pygubu-dizajnérov si naklikáte formulár, ktorý potom prepojíme s funkciami. Formulár je uložený ako XML v .ui súbore.

Návrh Python formuláre v pygubu-designer - Práca so súbormi v Pythone

Funkciu, ktorá sa zavolá po kliknutí na tlačidlo, v pygubu-dizajnérov nastavíme po vybraní tlačidla v záložke General -> Specific -> command.

Command v pygubu Designer pre Python - Práca so súbormi v Pythone

Funkciu, ktorá sa zavolá po vybraní položky z listbox, v pygubu-dizajnérov po vybraní listbox nastavíme v záložke Bindings.

Bindings v pygubu Designer pre Python - Práca so súbormi v Pythone

Pridáme tlačidlo "Načítať", ďalej ListBox listUzivatelu. Ďalej Entry na meno nového používateľa, Entry na jeho vek a Entry na dátum registrácie. K ovládacím prvkom pridáme nejaké labely. Tieto prvky môžeme zoskupiť do Frame. V ďalšom Frame budú 3 labely na detail užívateľa, tie pomenujeme jmenoLabel, vekLabel a registrovanLabel. Ďalšie 3 labely pridáme ako ich popisok. Nakoniec pridáme tlačidlo "Pridať" na pridanie používateľa. Ak to bolo moc rýchle, tu je obrázok výsledného formulára:

Formulár programu pre prácu s CSV súbory v Pythone - Práca so súbormi v Pythone

V reáli by bolo pridanie používateľov pravdepodobne prítomné v samostatnom formulári, ktorý by sa zobrazoval ako dialóg, ale nám to bude v tutoriálu stačiť takto.

Najskôr si musíme upraviť triedu Aplikace, aby sme využili náš naklikaný formulár (zdrojové kódy a gui.iu sú prípadne k stiahnutiu na konci článku, keby vám čokoľvek nešlo). Formulár získame načítaním súboru, potom nastavíme rodičia hlavnému framu a nakoniec napojíme obslužné funkcie. To všetko za nás v pozadí prevedie pygubu a my sa tak o nič nestaráme. Trieda Aplikace teraz vyzerá takto:

class Aplikace():

    def __init__(self, master):
        self.master = master
        self.db = Databaze("uzivatele.csv")
        self.builder = pygubu.Builder()
        self.builder.add_from_file("gui.ui")
        self.builder.get_object("Frame_1", self.master)
        self.builder.connect_callbacks(self)

A inicializujeme ju takto:

root = tkinter.Tk()
aplikace = Aplikace(root)
root.mainloop()

Z obsluhy tlačidla "Uložiť" odstránime vytvorenie testovacích používateľov. Samotné uloženie teraz vložíme do try - except bloku. Vieme totiž, že finally (teda with blok v našej databáze) výnimky nepohlcuje, čo tiež chceme a budeme na ne reagovať vo formulárové časti, kam reakcie logicky patrí. Upozornenie na chybu, teda komunikácia s užívateľom, priamo v triede Databaze by bolo zle. Po zachytení výnimky zobrazíme MessageBox s chybou. Obslužná metóda tlačidla bude teda vyzerať takto:

def tlacitkoNacistClicked(self):
    try:
        self.db.uloz()
    except:
        messagebox.showerror("Chyba", "Databázi se nepodařilo uložit, zkontrolujte přístupová práva k souboru.")

Obdobne upravíme metódu tlačidla "Načítať", iba po načítaní databázy vložíme objekty do ListBox u. Ten predtým vyprázdnime, aby nám tam nezostávali používatelia z predošlého načítanie. V reáli by sa načítanie vykonalo asi automaticky po spustení aplikácie a uloženie po ukončení, pre názornosť si to však ponecháme na tlačidlách. Metóda tlačidla "Načítať" teda vyzerá takto:

def tlacitkoNacistClicked(self):
    try:
        self.db.nacti()
    except:
        messagebox.showerror("Chyba", "Databázi se nepodařilo načíst, soubor zřejmě neexisituje.")
        return
    listbox = self.builder.get_object("listUzivatelu")
    listbox.delete(0,tkinter.END)
    for u in self.db.VratVsechny():
        listbox.insert(tkinter.END, u.jmeno)

Teraz spracujeme kliknutí na položku v listUzivatelu, ktoré vykoná zobrazenie detailu vybraného užívateľa do pripravených labelov:

def ziskejUzivatele(self, evt):
    listbox = self.builder.get_object("listUzivatelu")
    i = listbox.curselection()[0] + 1 if len(listbox.curselection()) > 0 else None
    if len(self.db.uzivatele) == 0 or i == None:
        return
    jmeno_label = self.builder.get_object("jmenoLabel")
    vek_label = self.builder.get_object("vekLabel")
    registovan_label = self.builder.get_object("registrovanLabel")
    u = self.db.uzivatele[i-1]
    jmeno_label["text"] = u.jmeno
    vek_label["text"] = u.vek
    registovan_label["text"] = u.registrovan.strftime("%d.%m.%Y")

Kód sme opodmínkovali pre prípad, že by nebol žiadny užívateľ vybraný (list by bol prázdny). Môžete si vyskúšať, že všetko funguje.

Posledné tlačidlo bez metódy je "Pridať" nového používateľa. Vytvoríme si obslužnú metódu. Vloženie bude veľmi jednoduché, prvok však musíme pridať ako do databázy, tak do listUzivatelu:

def tlacitkoPridatClicked(self):
    jmeno = self.builder.get_object("jmenoEntry").get()
    vek = self.builder.get_object("vekEntry").get()
    registrovan = self.builder.get_object("registrovanEntry").get()
    if jmeno == "" or vek == "" or registrovan == "":
        return
    registrovan = datetime.datetime.strptime(registrovan, "%d.%m.%Y")
    self.db.pridejUzivatele(jmeno, vek, registrovan)
    listbox = self.builder.get_object("listUzivatelu")
    listbox.delete(0,tkinter.END)
    for u in self.db.vratVsechny():
        listbox.insert(tkinter.END, u.jmeno)

Skúsime pridať nového používateľa:

Pridanie nového používateľa v CSV databáze v Pythone - Práca so súbormi v Pythone

Podobne by sme si mohli napísať aj mazanie užívateľov, ale to už nechám na vás. Zostáva nám ešte ošetriť cestu k súboru, aby viedla do zložky AppData, nie do zložky s programom. To vieme z tutoriálu Úvod do práce so súbormi v Pythone. Získanie cesty vykonáme v konstruktoru triedy Aplikace:

def __init__(self, master):
    self.master = master
    try:
        cesta = os.path.join(os.getenv("APPDATA"), "DatabazeUzivatelu")
        if not os.path.exists(cesta):
            os.mkdir(cesta)
    except:
        messagebox.showerror("Chyba", "Nepodařilo se vytvořit složku " + cesta + ", zkontrolujte prosím svá oprávnění.")
    self.db = Databaze(os.path.join(cesta, "uzivatele.csv"))
    self.builder = pygubu.Builder()
    self.builder.add_from_file("gui.ui")
    self.builder.get_object("Frame_1", self.master)
    self.builder.connect_callbacks(self)

A je to :)

Naša aplikácia je takmer hotová, ešte sa zamyslíme nad tým, čo sa stane, keď niekto do mena vloží bodkočiarka. Aplikácia sa rozbije. Preto budeme v metóde uloz() bodkočiarkami z mena odstraňovať. Keby sme robili aplikáciu, kde by sme ich potrebovali (čo sa nestáva príliš často), môžeme vybrať iný zástupný znak. Ak by sme chceli byť dokonalí, vložíme takú hodnotu sa bodkočiarkou do úvodzoviek. Potom sa však už nejde o jednoduché CSV a metóda split() nám prestane stačiť. Ďalej by sa to samozrejme dalo riešiť iným formátom. My si teda bodkočiarkami iba odstráňme, presnejšie ich nahradíme medzerami zmenou jediného riadku v metóde uloz():

hodnoty = [u.jmeno.replace(";", " "), str(u.vek), u.registrovan.strftime("%d.%m.%Y")]

A sme hotoví. Ak vám niečo nešlo úplne hladko, hotový projekt máte ako vždy v prílohe aj so zdrojovým kódom. V budúcej lekcii, Úvod do formátu XML v Pythone , sa pozrieme na formát XML.


 

Mal si s čímkoľvek problém? Stiahni si vzorovú aplikáciu nižšie a porovnaj ju so svojím projektom, chybu tak ľahko nájdeš.

Stiahnuť

Stiahnutím nasledujúceho súboru súhlasíš s licenčnými podmienkami

Stiahnuté 267x (3.12 kB)
Aplikácia je vrátane zdrojových kódov v jazyku Python

 

Predchádzajúci článok
Uloženie objektov do CSV v Pythone
Všetky články v sekcii
Práca so súbormi v Pythone
Preskočiť článok
(neodporúčame)
Úvod do formátu XML v Pythone
Článok pre vás napísal MQ .
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Používám hlavně Python a zajímám se o Deep Learning a vše kolem.
Aktivity