gui - datenbank (tabelle)

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Gast

hallo zusammen,

update 1!

nachstehend eine anwendung die eine gui erstellt, die zugriff auf sqltabellen erlaubt.
dabei habe ich versucht so abstrakt zu programmieren, dass tabellen unterschiedlicher struktur genutzt werden können und keine oder nur minimale anpassungen nötig sind.

das ziel konnte ich mal erreichen, deshalb poste ich das teil in seiner momentanen fassung.

ich habe damit 2 tabellen ausprobiert, die sehr unterschiedlich waren. die erste hat einen primary key, die andere nicht, zudem unterscheiden sie sich in feldanzahl wie datentypen.

was ist noch nicht erledigt:

- alles was mit design zu tun hat, grins, doch schon etwas besser, zumindest wird nicht mehr
wildsaumäßig ein tupel in die gui geschmissen, ggg

- autoaktualisierung der ansicht,
(wird wohl bald erledigt sein)

- es gibt soch noch einiges an code der besser zusammengefasst, vereinfacht werden kann
naja, das wird wohl nie ganz erledigt sein.

- da viel code aus einer alten anwendung von mir wiederverwendet wurde, ist die namensgebung nicht einheitlich und sicher noch ein manko im codedesign.

was wurde sonst gemacht:
ich habe einige klassenvariablen gekillt, denke ist für die performance nicht uninteressant.

eine horizontale scrollleiste

fenster baut sich entsprechend der feldmenge dynamisch auf,
Eingabe-, BearbeitungsFenster positionieren sich neben dem HauptFenster, position wird entsrpechend der aktuellen breite des HF ermittelt.

Code: Alles auswählen


#!/usr/bin/env python


from Tkinter import*
from ScrolledText import*
import tkMessageBox
import sys
from database import *
           
        

               
class Fenster:


    #Abstand der Elemente
    a_x=5 #Abstand horizontal
    a_y=5 #Abstand vertikal

    #Die Buttons bekommen alle dieselbe Breite
    b=20

    #Farbe wird auch von la verwendet
    f="#00ff00"

    lt=""

    
    def __init__(self):

        raise NotImplementedError("Abstract class")

    

    def prepare(self):

        self.root.resizable(0,0)

        self.root.protocol("WM_DELETE_WINDOW",self.mainexit)

        la=Label(self.root,bg=self.f,text="///GARO_GUI")
        la.grid(row=0,column=0,            
                     columnspan=2,
                     padx=self.a_x,pady=self.a_y)
      
        la_1=Label(self.root,bg=self.f,text=self.lt)
        la_1.grid(row=1,column=0,
                       columnspan=2,
                       padx=self.a_x,pady=self.a_y)
       
        button=Button(self.root,
                           text="Prog. Beenden",
                           width=10,command=self.ende)
        button.grid(row=15,column=0,
                         columnspan=2,
                         padx=10,pady=10)



    def ende(self):

        antwort=tkMessageBox.askyesno\
                 ("Warnung","Sicher beenden?")
        if antwort==1:
            sys.exit(0)


    def mainexit(self):
        
        self.root.withdraw()

   
    
  
class HauptFenster(Fenster):

    lt="Ausgabe"

       
    def __init__(self,host,user,db,db_table,passwd=''):

        self.root=Tk()

        self.root.wm_geometry('+20+20')

        self.prepare()

        self.root.title("Hauptfenster")
          
        self.database=DataBase(host,user,db,db_table,passwd)

        self.db_table=db_table
        
        choice=StringVar()

        self.cols_names=[elements[0] for elements in self.database.db_table_cols
                         if 'auto_increment' not in elements]


        li_1width=len(self.cols_names)*12

        self.s_cols_names=", ".join(self.cols_names)


        scb_v=Scrollbar(self.root, orient="vertical")
        scb_h=Scrollbar(self.root, orient="horizontal")

        self.li_1=Listbox(self.root,
                          width=li_1width,height=8,
                          yscrollcommand=scb_v.set,
                          xscrollcommand=scb_h.set)
        
        scb_v["command"]=self.li_1.yview
        scb_h["command"]=self.li_1.xview
        
        self.li_1.grid(row=2,column=0,
                       columnspan=2,
                       padx=self.a_x,pady=self.a_y)
        
        scb_v.grid(row=2,column=2,
                      padx=self.a_x,pady=self.a_y)
        
        scb_h.grid(row=3,column=0,
                        columnspan=2,
                        padx=self.a_x,pady=self.a_y)
                       

        b_1=Button(self.root,width=self.b,text="Alle Daten",
                        command=lambda:
                        self.list_data
                        (result=self.database.get_data
                        ("select %s from %s"%(self.s_cols_names,self.db_table))))
        b_1.grid(row=4,column=0,
                      padx=self.a_x,pady=self.a_y)
        

        b_2=Button(self.root,width=self.b,
                        text="Loeschen",command=self.ask)
        b_2.grid(row=4,column=1,
                      padx=self.a_x,pady=self.a_y)
        
        
        b_3=Button(self.root,width=self.b,text="Sortieren",
                        command=lambda:
                        self.list_data
                        (result=self.database.get_data
                        ("select %s from %s order by %s"%(self.s_cols_names,self.db_table,choice.get()))))
        b_3.grid(row=5,column=0,
                      padx=self.a_x,pady=self.a_y)
        

        b_4=Button(self.root,width=self.b,text="Eingabe",
                        command=lambda:
                        EingabeFenster
                        (self.root,self.database,
                         self.db_table,
                         self.root.winfo_width()))
        b_4.grid(row=5,column=1,
                      padx=self.a_x,pady=self.a_y)


        b_5=Button(self.root,width=self.b,text="Suchen",
                        command=lambda:
                        SuchFenster
                        (self,self.root,self.database,self.db_table))
        b_5.grid(row=6,column=0,
                      padx=self.a_x,pady=self.a_y)


        b_6=Button(self.root,width=self.b,text="Bearbeiten",
                        command=lambda:
                        BearbeitungsFenster
                        (self.root,self.database,
                         self.db_table,self.li_1.get("active"),
                         self.root.winfo_width()))
        b_6.grid(row=6,column=1,padx=self.a_x,pady=self.a_y)


        for i in range(len(self.cols_names)):

            rb=Radiobutton(self.root,text=self.cols_names[i],
                        value=self.cols_names[i],
                        variable=choice)
            rb.grid(row=i+7,column=1,
                         padx=self.a_x,pady=self.a_y)

            if i==0:
                rb.select()

        self.list_data(result=self.database.get_data("select %s from %s"%(self.s_cols_names,self.db_table)))




    def list_data(self,result):
        
        self.li_1.delete(0,END)
        result=[list(element) for element in result]

        for element in result:
            for i in range(len(element)):
                element[i]=str(element[i])
                
        result=["   ".join(element) for element in result]

        for elements in result:
                self.li_1.insert("end",elements)
            

    def get_selected(self,action):

        selected=self.li_1.get("active")
        selected=selected.split()
        selected=[str(selected[i]).replace(str(selected[i]),'"'+str(selected[i])+'"')
                     for i in range(len(selected))]
                     
        target=[self.cols_names[i]+"="+selected[i]
                       for i in range(len(selected))]
        target=" and ".join(target)

        check=self.database.get_data("select * from %s where %s"%(self.db_table,target))
        check=check[0][0]

        action=action%check
        return action
    

    def ask(self):

        answer=tkMessageBox.askyesno("Warnung",
                                     "Wollen Sie den gewaehlten Datensatz sicher loeschen ?")
        if answer==1:
            self.database.set_data(action=self.get_selected("delete from %s where %s = %s"%(self.db_table,
                                             self.database.db_table_cols[0][0],
                                             "%s")))
        else:
            pass

            

       
class EingabeFenster(Fenster):

    lt="Eingabe/Bearbeitung"

    
    def __init__(self,root,database,db_table,hfwidth):

        self.root=Toplevel(root)

        self.root.wm_geometry('%s+20'%('+'+str(hfwidth+40)))

        self.root.title("Eingabefenster")

        self.prepare()

        self.database=database
        self.db_table=db_table


        self.cols_names=[elements[0] for elements in self.database.db_table_cols
                         if 'auto_increment' not in elements]

        self.s_cols_names=", ".join(self.cols_names)

        self.entrylist=[]

        for i in range(len(self.cols_names)):
            
            la=Label(self.root,
                          text=self.cols_names[i])
            la.grid(row=i+2,column=0)

            entry=Entry(self.root)
            entry.grid(row=i+2,column=1,
                            padx=self.a_x,pady=self.a_y)
            self.entrylist.append(entry)

        b_1=Button(self.root,width=self.b,
                        text="Eintragen",
                        command=lambda:
                        self.database.set_data
                        (action=self.set_sql
                        ("insert into %s (%s) values (%s)")))
                        
        b_1.grid(row=7,column=1,
                      columnspan=2,
                      padx=self.a_x,pady=self.a_y)
        
       
    def get_entries(self):

        entries=[element.get() for element in self.entrylist]
        
        for i in range(len(entries)):
            test=entries[i].find(" ")
            if test and test !=-1:
                entries[i]=entries[i].replace(entries[i][test],"/")
                
        for element in self.entrylist: element.delete(0,"end")
        
        entries=[entries[i].replace(entries[i],'"'+entries[i]+'"')
                      for i in range(len(entries))]

        return entries

    
    def set_sql(self,action):
        
        entries=self.get_entries()

        s_entries=", ".join(entries)
        
        action=action%(self.db_table,self.s_cols_names,s_entries)
        return action




class BearbeitungsFenster(Fenster,EingabeFenster):

    lt="Bearbeitung"
    

    def __init__(self,root,database,db_table,selected,hfwidth):
        
        self.selected=selected
        self.selected=self.selected.split()

        EingabeFenster.__init__(self,root,database,db_table,hfwidth)
        
        self.root.title("Bearbeitungsfenster")

        for i in range(len(self.entrylist)):
            self.entrylist[i].insert(0,self.selected[i])

        b_1=Button(self.root,width=self.b,
                        text="Eintragen",
                        command=lambda:
                        self.database.set_data
                        (action=self.set_sql
                        ("update %s set %s where %s=%s")))
                        
        b_1.grid(row=7,column=1,
                      columnspan=2,
                      padx=self.a_x,pady=self.a_y)
        
    
    def set_sql(self,action):

        entries=self.get_entries()

        result=[self.cols_names[i]+"="+entries[i]
                for i in range(len(entries))]
        result=", ".join(result)

        self.selected=list(self.selected)
        self.selected=[str(self.selected[i]).replace(str(self.selected[i]),'"'+str(self.selected[i])+'"')
                       for i in range(len(self.selected))]
        
        target=[self.cols_names[i]+"="+self.selected[i]
                for i in range(len(self.selected))]
        target=" and ".join(target)

        check=self.database.get_data("select * from %s where %s"%(self.db_table,target))
        check=check[0][0]
        
        self.cols_names_b=[elements[0] for elements in self.database.db_table_cols]

        action=action%(self.db_table,result,self.cols_names_b[0],check)
        return action
       

                   
class SuchFenster(Fenster):

    lt="Suche"


    def __init__(self,hf,root,database,db_table):

        self.root=Toplevel(root)

        self.root.title("Suchfenster")

        self.prepare()
        
        choice=StringVar()
        self.database=database
        self.db_table=db_table


        entry=Entry(self.root)
        entry.grid(row=3,column=0)

        for i in range(len(hf.cols_names)):

            rb=Radiobutton(self.root,text=hf.cols_names[i],
                                value=hf.cols_names[i],
                                variable=choice)
            rb.grid(row=i+2,column=1,
                         padx=self.a_x,pady=self.a_y)

            if i==0:
                rb.select()
           

        b_1=Button(self.root,text="Suche",
                        command=lambda:
                        hf.list_data
                        (result=self.database.get_data
                        ("select %s from %s where %s= '%s'"%(hf.s_cols_names,
                                                             self.db_table,
                                                             choice.get(),
                                                             entry.get()))))
                        
        b_1.grid(row=9,column=0)


if __name__ == "__main__":

    hf=HauptFenster("localhost","username","datenbank","tabelle","passwort")
    #hf=HauptFenster("localhost","username","andere datenbank", usw)

    mainloop()
hier noch das modul database

Code: Alles auswählen

#!/usr/bin/env python


import MySQLdb
from _mysql_exceptions import *


class DataBase:


    def __init__(self,host,user,db,db_table,passwd=''):
        
        try:
            self.conn=MySQLdb.connect(host=host,
                                      user=user,
                                      db=db,
                                      passwd=passwd)
   
             
        except OperationalError, msg:
            print msg[1]

        self.db_table_cols=self.get_data("show columns from %s"%db_table)

    
    def get_data(self,action):

        cursor=self.conn.cursor()
        cursor.execute(action)
        result=cursor.fetchall()
        cursor.close()
        return result


    def set_data(self,action):

        cursor=self.conn.cursor()
        cursor.execute(action)
        cursor.close()


    def close(self):
        self.conn.close()
kommentare erwünscht, vielleicht habt ihr nützliche tipps was ich noch ändern, überarbeiten sollte, bevor es in die 3. runde geht oben genannte todo list umzusetzen.

ich bedanke mich an dieser stelle noch einmal bei allen in diesem forum, die mir bei diesem projekt bis jetzt schon mit wertvollen tipps geholfen haben.

mfg

rolgal
Zuletzt geändert von Gast am Samstag 23. April 2005, 23:35, insgesamt 1-mal geändert.
CM
User
Beiträge: 2464
Registriert: Sonntag 29. August 2004, 19:47
Kontaktdaten:

Kompliment, sieht recht eindrucksvoll aus - zumindest der Code, den Rest kann ich nicht beurteilen, weil ich Tkinter nicht installiert habe. Schön finde ich es auch zu wissen, daß wir jetzt einen MySQL-Experten unter uns haben ;-) - werde bei Gelegenheit darauf zurückgreifen, wenn es recht ist.

Gruß,
Christian
Gast

hi christian,

danke für das kompliment, auch wenn es noch viel zu tun und verbessern gibt, bin ich doch auch schon etwas zufrieden damit, denke dass ich mit dem programm einen schritt nach vorne gemacht habe.
den Rest kann ich nicht beurteilen, weil ich Tkinter nicht installiert habe.
tja das design braucht noch viel pflege, dass mach ich immer zuletzt, ist was für die sommerferien :D
Schön finde ich es auch zu wissen, daß wir jetzt einen MySQL-Experten unter uns haben Wink - werde bei Gelegenheit darauf zurückgreifen, wenn es recht ist.
naja, experte ist sicherlich zuviel der ehre, aber ich kann es ja mal als vorschuss nehmen und sehen dass ich dem in zukunft gerecht werde :D

gruß

rolgal
Gast

hallo zusammen,

wie oben angeführt gibt es ein erstes update,

mfg

rolgal
tabellarGast

Hi rolgal,

ich bin zwar nicht der Prog Profi, aber ich hab doch einiges mit DBs und den entsprechenden Zugriffen darauf zu tun. Ein Vorschlag von mir wäre, dass du die SQL Statements aus der Fensterklasse rausnimmst und in deiner database Klasse integrierst. Ziel ist immer eine allgemeine DB API zu erstellen, damit die eigentliche Anwendung nicht vom Datenbanktyp abhängig ist. So kann dann leicht eine andere DB dahintergesteckt werden.

Gruss Tabellar
Gast

hallo tabellarGast,

danke für deine anregung, ich werde das mal durchdenken und ausprobieren,
da ich mich eigentlich nur mit mysql beschäftige bin ich auf deine idee nicht gekommen.

grüße,


rolgal
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Sowas für SQLite wäre sicher ziemlich nett :)
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
TabellarGast

Ich hätte da noch ein paar Anregungen:

- Start/Initialisierung sollte OHNE Datenbankverbindungsaufbau geschehen
In der Laufzeitumgebung müsste es dann eine CONNECT Funktion geben, die mit der gewünschten Datenbank verbindet. Am schicksten wäre es natürlich, man könnte das ganze so kapseln, dass man z.B. MySQL, PostgreSQL, SQLite, Gadfly, MSAccess, CSV, XML ... auswählen kann :P

- Das ganze würde dann einen Datenbankhandler voraussetzen, der je nach gewünschter Datenbank das entsprechende DB API verwendet. Z.B. rolgalMySQLAPI.py, tabellarPGSQLAPI.py, leonidasSQLiteAPI.py, etc..

- Das ganze bräuchte dann so eine Art Plugin Mechanismus. Neue Datenbank, neues DBAPI Modul und los geht's...

Wenn ich heute abend dazu komme, teste ich mal Dein Programm. Dazu muss ich aber mal schauen, wo ich gerade eine MySQL DB installiert habe.
Meine derzeitige Lieblingsdatenbank ist PostgreSQL. Wenn ich dazu komme, mach ich dann mal eine DB API für PostgeSQL.

Damit mehrere hier im Forum mittesten können, müsste man vielleicht zuerst eine einfachere Datenanbindung haben, z.B. eine CSV oder XML Datei. Damit das alles dann auch funktioniert, liegt alleine am Datenbankhandler, der die nötige Datenkapselung mitbringt.

Tabellar
Gast

hallo TabellarGast,

klingt alles gut und schön, man darf aber nicht die zielsetzung aus den augen verlieren, eine gui, die mit verschiedenen mysqltabellen umgehen kann, um z.b. die klassischen tabellen einer webseite am lokalen rechner zu verwalten, die haben oft ja nur eine tabelle.

dabei wollte ich, dass es entweder keine oder nur minimale anpassungen braucht...

inzwischen bastel ich daran, dass die anwendung auch mit datenbanken umgehen kann, die aus mehreren tabellen besteht, so weit funktioniert es auch schon, da ich aber mit dem code noch nicht zufrieden bin und manches sicher noch schöner gelöst werden kann, habe ich es noch nicht reingestellt, kommt aber bald

:D

auf was ich raus will, es gibt ständig was zu tun, und ich werde mich sicher mal mit deinen vorschlägen auseinandersetzen, aber die oben genannte zielsetzung soll zuerst optimiert werden auch andere dinge sind zuerst zu erledigen, die auf der todoliste stehen.

so muss das laufen, sonst wirds chaotisch,

danke trotzdem, ich hoffe du hast mich nicht falsch verstanden,

grüße

rolgal

i
BlackJack

Wenn Du Dich erstmal auf Datenbanken beschränkst, deren Python-Modul die DB API 2.0 unterstützen, dann sind die grössten Unterschiede eigentlich nur der Verbindungsaufbau, also was konkret bei `connect()` übergeben werden kann/muss, und wie die Platzhalter bei SQL Anweisungen aussehen, wenn man das Datenbankmodul bei `execute()` Werte einfügen/escapen lässt.
tabellarGast

Hi rolgal,

klar, Deine Zielsetzung darfst Du nicht aus den Augen verlieren!
Was ich da geschrieben habe ist vielleicht wirklich zu viel des guten... :roll:
Aber als Denkansatz waren die Gedanken vielleicht ganz gut.

Wie schon BlackJack erwähnte, wenn Du Python DB API 2.0 unterstützende
Module verwendest, passt das ganze schon. Trotzdem nochmal, versuch doch
schön am klassischen drei Schicht Modell zu bleiben:
1. Client (GUI, CLI, Interpretermode)
2. Funktionsbibliothek [table=Table("books",db), table.insert("v1" , "v2") etc.]
3. Data Storage (DB)

Tabellar
Gast

hallo,...


....also auf grund der tatsache, dass meine wichtigste tätigkeit eigentlich eine ganz andere ist:
http://crossoverguitar.weberanto.net, die webseite ist natürlich nicht gemeint, werde ich allein wohl eine ewigkeit brauchen, die ganzen wertvollen anregungen umzusetzen.
mich nervt, dass es immer einen schöne lange zeit braucht bis man wieder in der materie richtig drin ist, wenn man abstand davon hatte :roll:


also stellt sich die frage, ob sich nicht ein paar leute finden, die gemeinsam dran weiterbasteln wollen?

grüße

rolgal
TabellarGast

... ich spiele auch gerne Gitarre, zumindest früher ;-) . Ich werde mit meinen bescheidenen Programmierkenntnissen mal eine databasewrapper Klasse für Dein Programm erstellen, damit die DB-Funktionalität von dem GUI getrennt ist. Braucht aber ein bisschen, da ich viel am Arbeiten bin (Brötchen) und am Abend dann noch meine eigenen Projekte habe. Aber das Thema databaseWrapper und TKinter interessiert mich...

Tabellar
Gast

hi tabellargast,

super, bin schon gespannt auf deinen vorschlag,...

habe mir auch schon einige gedanken gemacht,...

wenn es richtig gut ist, kriegst ein paar gratisstunden :D für dein gitarrespiel...

grüße

rolgal
Gast

also, ich dachte mal in kleinen schritten:

Code: Alles auswählen

>>> sql={"mysql":{"list":"select* from user"},"posql":{"list":"select bla bla bla"}}
>>> db_type="mysql"
>>> sql[db_type]['list']
'select* from user'
etwas weiter gedacht...

Code: Alles auswählen

>>> sql={"mysql":{"list":"select* from user"},"posql":{"list":"select bla bla bla"}}
>>> def sql_action(db_type,command,host,user,database,password):
	
	    if db_type=="mysql":
		    from dbApis import MySqlApi
		    database=MySqlApi(host,user,database,password)
		    result=database.get_data(sql[db_type][command])
		    return result

	
>>> sql_action("mysql","list","localhost","rolgal","crossover","ein passwort")
zum besseren verständnis, dbApis könnte so aussehen z.b.

Code: Alles auswählen

class MySqlApi:

    import MySQLdb
    from _mysql_exceptions import *


    def __init__(self,host,user,db,passwd=''):

        self.db=db
        
        try:
            self.conn=MySQLdb.connect(host=host,
                                      user=user,
                                      db=db,
                                      passwd=passwd)
   
             
        except OperationalError, msg:
            print msg[1]


    
    def get_data(self,action):

        cursor=self.conn.cursor()
        cursor.execute(action)
        result=cursor.fetchall()
        cursor.close()
        return result


    def set_data(self,action):

        cursor=self.conn.cursor()
        cursor.execute(action)
        cursor.close()
 

    def close(self):
        
        self.conn.close()
so in etwas könnte das hinhauen, oder?


die frage ist:
wann und wie ermittelt man am besten den typ, wenn man es überhaupt so macht wie oben angedacht...

güße

rolgal
BlackJack

Wie es aussieht hast Du einen SQL-Ausdruck für jede Datenbank? Aber gerade SQL sollte doch für jede (SQL-)Datenbank gleich sein?

Oder habe ich da jetzt etwas missverstanden?
Gast

hi blackjack,

sollte, ist es aber nicht immer ganz, allerdings muss ich sagen, dass ich ausser mit mysql und gadfly keine erfahrung mit datenbanken habe.
gadfly gibts eigentlich nur in zope, hmm...

hier mal ein link, der unterschiede zwischen mysql und postgresql beschreibt, vom ersten lesen her, sollte es möglich sein mit einer api auszukommen.


http://www.pronix.de/pronix-371.html


das zitat von einer webseite (http://www.linux-magazin.de/Artikel/aus ... lebri.html)
spricht wieder nicht so dafür,
gut argumentiert, allerdings traue ich den entwicklern von mysql schon zu sich etwas bei "auto_increment" gedacht zu haben.
11/02, S. 104: Im Kasten "Unterschiede bei PostgreSQL" ist zu lesen, dass PostgreSQL keine Eigenschaft »auto_increment« kennt und man daher umständlich ein »CREATE SEQUENCE« machen muss. Viel einfacher ist es aber, den Datentyp »SERIAL« zu verwenden, der wird automatisch zu einem Ganzzahltyp mit angeschlossener Sequence.

So etwas passiert oft, wenn man sich zunächst auf MySQL bezieht und dann die Unterschiede von PostgreSQL dazu darstellt. Da PostgreSQL erstens im Gegensatz zu MySQL eine richtige Datenbank ist (ACID-Kriterien) und außerdem dem SQL-Standard weit näher ist (auch näher als Oracle), sollte jeder, der sich auch nur ein bisschen mit Datenbanken auskennt, sich eher auf PostgreSQL beziehen und dann die (vielen) Abweichungen von MySQL darstellen.
da denke ich mir dann eher wieder:wenn es dann doch wieder unterschiede gibt und wenn man auch berücksichtigt, dass datumsfunktionen anders funzen, dann entwerfe ich doch besser etwas das verschiedene apis hat, deshalb auch das skizzierte dictionary usw.

naja, und wenn der user dann erst wieder lesen muss, welche dinge er berücksichtigen muss, wenn er seine tabellen, datenbanken mit meiner gui verwenden will, ist es eigentlich nicht wirklich userfreundlich, allein die ansage: auto_increment kann nicht verwendet werden, weil.....usw. klingt für jmd. der mysql verwendet wahrscheinlich nicht verlockend.


freilich die tatsächlichen sqlanweisungen sind gleich (behaupte ich mal), aber das drumherum macht es eben schwierig.

sorry, wenn ich so viele tippe, aber ich denke so vor mich hin und tippe und denke, warum ich immer so viel denke und tippe, wenn ich schon ne flasche wein geleert habe :D



bis bald

rolgal
Gast

Hallo zusammen,

es ist schon etwas spät, aber trotzdem noch ein kleiner comment.

Das Design für den Zugriff auf eine Datenbank ist ein Endlosthema. Zu unterschiedlich sind die individuellen Anforderungen. Einmal ist die Geschwindigkeit das Hauptthema, einmal die Datenbankunabhängigkeit, einmal Zugriff über ein Webinterface etc.

Ziel der Anwendung von Rolgal ist doch die einfache Pflege von Tabellen (Anzeigen, Suchen, Löschen, Editieren, Einfügen) ohne das Erstellen von tabellenspezifischen Formularen(Fenstern). EINE Anwendung für beliebige Tabellen. Also müssen wir auf das Erzeugen der individuellen Datenbanktabellen (MySQL, PostgreSQL, Gadfly, etc. mit autoincrement, serial usw.) hier gar nicht eingehen.

Das GUI braucht doch lediglich Tabellenangaben in der Form table.getColumns, table.getItems, table.deleteItem(4711) etc.
Diese Funktionen werden von einem Datenbankmanager oder -wrapper oder einer speziellen Tabellenklasse bereitgestellt. Eben diese "client neutrale" Funktionsbibliothek muss dann durch die individuellen DBApis erweitert werden:

(GUI)client->DBManager/TableClass->DbAPI->DB

Man kann das ganze dann auch noch die Spitze treiben, in dem man den DBWrapper so schreibt, als ob man Tabellen wie Python Listen behandelt.
Bsp.:
books=Table(books,db)
for i in books:
print i

Schaut Euch hierzu mal folgenden Artikel an:
http://www.devx.com/dbzone/Article/22093/1954?pf=true

Tabellar
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Dank Piddon habe ich meinen Zugang zum Forum wieder :P Danke!

Ich kämpfe gerade mit den einfachsten Dingen herum. Ich habe einen MySQL Server, auf den ich via VPN und MySQLdb nicht connecten kann (Zugriffsrechte???) und bei Postgres finde ich das MySQL Pendant "Show columns from table;" nicht.

Ich würde gerne mal die TKinter Fenster von rolgal sehen, damit ich einen Überblick über das Programm bekomme. Vielleicht gibt es ja ein paar Screenshots???

Tabellar
tabellar
User
Beiträge: 186
Registriert: Mittwoch 4. September 2002, 15:28

Also, ich hab jetzt eine "TableWrapper" Klasse, die die benötigten Funktionen für die Hauptfensterklasse bereitstellt. SQL oder sonstige Dinge sind grösstenteils schon aus der "HauptFenster" Klasse eliminiert. Mit Tk habe ich bisher noch nicht viel gemacht, wenn GUI, dann eher im CGI Bereich...

Bei der Trennung der Klassen "Hauptfenster" und "TableWrapper" lasse ich die Datenbankverbindung im Moment weg und füttere die "Hauptfenster" Klasse lediglich mit "Datenlisten", wie sie nachher bei der Datenbankabfrage via SQL erzeugt werden.

Ziel ist nachher der Zugriff auf MySQL und PostgreSQL Datenbankserver sowie auf ein XML File mit einer "datenbankähnlichen" Struktur (s.u.). Vorteil wäre, dass Interessierte das Programm verwenden können, ohne die entsprechenden DB-Server installiert zu haben ;-) .

Code: Alles auswählen

<xmldb>

 <table name="tn1">
   <row>...
   <row>...
 </table>

 <table name="tn2">
   <row>...
   <row>...
 </table>

</xmldb>
Das ganze soll die 3-Schicht Architektur verdeutlichen. Eine CGI Applikation wäre so auch schnell möglich zu erstellen.

Tabellar
Antworten