gui - datenbank (tabelle)
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?
Oder habe ich da jetzt etwas missverstanden?
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.
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
bis bald
rolgal
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.
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.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.
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
bis bald
rolgal
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
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
Dank Piddon habe ich meinen Zugang zum Forum wieder 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
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
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 .
Das ganze soll die 3-Schicht Architektur verdeutlichen. Eine CGI Applikation wäre so auch schnell möglich zu erstellen.
Tabellar
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>
Tabellar
hallo tabellar,
in meinem code gibt es eine regel (noch als einfach if-anweisung):
datenfelder die eben auto_increment aufweisen werden ignoriert beim anzeigen, beim erstellen der eingabefelder, der radiobuttons.
natürlich nicht beim schrieben von daten(!)
da postgresql das nicht kennt und ich in einer allfälligen api für versch. sqldbs mich auf einen gemeinsamen nenner einigen müsste, müsste der user drauf aufmerksam gemacht werden, dass er mysql, die auto_increment verwendet, vergessen kann.
freilich liessen sich alle spezfika einer db berücksichtigen, aber irgendwie riecht mir das nach frickeln. im sinne von elendslangen if anweisungen usw.
und wenn man da loslegt, finden sich sicherlich noch viele "auto_increments", deshalb war meine idee gleich für jede db eine eigene api, auch wenn sich viele sqlanweisungen möglicherweise wiederholen.
ich habe deinen thread in allgemeine fragen gelesen bez. "show columns..."
da ist es also schon das zweite auto_increment:d
mfg
rolgal
[/quote]
die sache mit auto_increment ist nicht nur für das erstellen von tabellen wichtig:Also müssen wir auf das Erzeugen der individuellen Datenbanktabellen (MySQL, PostgreSQL, Gadfly, etc. mit autoincrement, serial usw.) hier gar nicht eingehen.
in meinem code gibt es eine regel (noch als einfach if-anweisung):
datenfelder die eben auto_increment aufweisen werden ignoriert beim anzeigen, beim erstellen der eingabefelder, der radiobuttons.
natürlich nicht beim schrieben von daten(!)
da postgresql das nicht kennt und ich in einer allfälligen api für versch. sqldbs mich auf einen gemeinsamen nenner einigen müsste, müsste der user drauf aufmerksam gemacht werden, dass er mysql, die auto_increment verwendet, vergessen kann.
freilich liessen sich alle spezfika einer db berücksichtigen, aber irgendwie riecht mir das nach frickeln. im sinne von elendslangen if anweisungen usw.
und wenn man da loslegt, finden sich sicherlich noch viele "auto_increments", deshalb war meine idee gleich für jede db eine eigene api, auch wenn sich viele sqlanweisungen möglicherweise wiederholen.
ich habe deinen thread in allgemeine fragen gelesen bez. "show columns..."
da ist es also schon das zweite auto_increment:d
mfg
rolgal
[/quote]
Hi Rolgal,
Diese ColumnsList erhält die HF-Klasse durch eine Anfrage bei der TableWrapper Class. Z.B. so:
>>> self.col_names=self.tablewrapper.getColumnsAsList(tablename)
Die TableWrapper Class agiert sozusagen dann als API oder "Gate" Klasse, die wiederum die individuellen DB APIs beinhaltet.
Solche APIs wären dann zb. MySQL.py, PgSQL.py, XMLdb.py, die alle die Methode "getColumnsAsList" via "import" zur Verfügung stellen mit Übergabe der entsprechenden ColumnsList, OHNE Primärschlüssel (autoincrement, serial, etc.).
Super wäre also so etwas in der Art:
HF-Class
TableWrapper Class
MySQL.py API
PgSQL.py API
XMLdb.py API
Ich werde mich im nächsten Schritt mal um die PgSQL und XML Geschichte kümmern.
Gruss Tabellar
Das habe ich schon erkannt , letztendlich braucht Deine Hauptfensterklasse (HF-Klasse) ja nur die Zuweisung von "self.cols_names" bei der Instantiierung durch die Angabe einer "ColumnsList"....in meinem code gibt es eine regel (noch als einfach if-anweisung):
datenfelder die eben auto_increment aufweisen werden ignoriert beim anzeigen, beim erstellen der eingabefelder, der radiobuttons.
natürlich nicht beim schrieben von daten(!)...
Diese ColumnsList erhält die HF-Klasse durch eine Anfrage bei der TableWrapper Class. Z.B. so:
>>> self.col_names=self.tablewrapper.getColumnsAsList(tablename)
Die TableWrapper Class agiert sozusagen dann als API oder "Gate" Klasse, die wiederum die individuellen DB APIs beinhaltet.
Solche APIs wären dann zb. MySQL.py, PgSQL.py, XMLdb.py, die alle die Methode "getColumnsAsList" via "import" zur Verfügung stellen mit Übergabe der entsprechenden ColumnsList, OHNE Primärschlüssel (autoincrement, serial, etc.).
Super wäre also so etwas in der Art:
HF-Class
TableWrapper Class
MySQL.py API
PgSQL.py API
XMLdb.py API
Ich werde mich im nächsten Schritt mal um die PgSQL und XML Geschichte kümmern.
Gruss Tabellar
Ich hab hier jetzt mal einen ersten Entwurf für den GUI Datenbank Client von rolgal. Das ganze ist natürlich noch nicht fertig, aber die Trennung von GUI und der Datenbank ist erfolgt. Im Moment kann ich auf PostgreSQL und XML Datenbanken (db.xml) zugreifen (Daten anzeigen und Daten neu einfügen) .
Das db-GUI greift über das TableWrapper Modul und den entsprechenden DB-DAOs Modulen (pgsqlDAO, xmlDAO - DAO=Data Access Objects) auf die Daten zu. Auf die XML Datenbankdatei wird über das interne Python Modul "MiniDOM" zugegriffen. Der dbGUI Client kann somit allein mit Python Bordmitteln genutzt werden. Ein DB-Server muss nicht installiert sein.
Durch die Trennung des GUIs von dem DAO Modul, kann jetzt die Funktionalität des GUIs einfacher verbessert werden.
Mögliche weitere Schritte sind:
GUI:
- Datenbankauswahl via Dialogfenster
- Tabellenauswahl
- Schönere Datenansicht
DBDAO:
- Implementation des mySQL DAO Moduls (ich kann nicht auf meinen Gentoo MySQL Server von extern zugreifen...)
- Implementation sqliteDAO
- Bearbeiten und Löschen Funktion
Viel Spass
Tabellar
Db GUI Client
tableWrapper Modul:
pgsqlDAO Modul:
xmlDAO Modul:
XML Datenbankdatei db.xml :
Das db-GUI greift über das TableWrapper Modul und den entsprechenden DB-DAOs Modulen (pgsqlDAO, xmlDAO - DAO=Data Access Objects) auf die Daten zu. Auf die XML Datenbankdatei wird über das interne Python Modul "MiniDOM" zugegriffen. Der dbGUI Client kann somit allein mit Python Bordmitteln genutzt werden. Ein DB-Server muss nicht installiert sein.
Durch die Trennung des GUIs von dem DAO Modul, kann jetzt die Funktionalität des GUIs einfacher verbessert werden.
Mögliche weitere Schritte sind:
GUI:
- Datenbankauswahl via Dialogfenster
- Tabellenauswahl
- Schönere Datenansicht
DBDAO:
- Implementation des mySQL DAO Moduls (ich kann nicht auf meinen Gentoo MySQL Server von extern zugreifen...)
- Implementation sqliteDAO
- Bearbeiten und Löschen Funktion
Viel Spass
Tabellar
Db GUI Client
Code: Alles auswählen
#!/usr/bin/env python
#Modul uniDbGUI - Universaler Datenbank GUI Client
from Tkinter import *
import sys
import tkMessageBox
import tableWrapper
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=18,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")
#instantiierung DbWrapper...
self.tablewrapper=tableWrapper.TableWrapper()
# Manuelle Datenbankauswahl via Angabe
# des Datenbanktyps: (später durch Dialogauswahl...)
# PgSQL
# MySQL
# XML
self.tablewrapper.connect('XML','host','dbname','user')
self.cols_names=self.tablewrapper.getTableColumnsList()
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(self.tablewrapper.getTableColumnsData()))
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.tablewrapper,
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)
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)
self.root.title("Hauptfenster-Connected...")
#radio buttons...
choice=StringVar()
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()
def get_selected(self,action):
"""muss noch gemacht werden"""
def ask(self):
"""muss noch gemacht werden"""
class EingabeFenster(Fenster):
lt="Eingabe/Bearbeitung"
def __init__(self,root,tablewrapper,hfwidth):
self.root=Toplevel(root)
self.root.wm_geometry('%s+40'%('+'+str(hfwidth+80)))
self.root.title("Eingabefenster")
self.prepare()
self.tablewrapper=tablewrapper
self.cols_names=self.tablewrapper.getTableColumnsList()
self.s_cols_names=", ".join(self.cols_names)
self.entrylist=[]
for i in range(len(self.cols_names)):
label=Label(self.root,text=self.cols_names[i])
label.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,text="Eintragen",command=self.printEntries)
b_1.grid(row=(len(self.cols_names)+2),column=2,padx=self.a_x,pady=self.a_y)
def printEntries(self):
"""---"""
entryTextList=[]
for element in self.entrylist:
entryTextList.append(element.get())
for element in self.entrylist:
element.delete(0,"end")
print self.cols_names
print entryTextList
self.tablewrapper.insertTableColumnsData(self.cols_names,entryTextList)
if __name__=="__main__":
hf = HauptFenster()
mainloop()
Code: Alles auswählen
#!/usr/bin/env python
#Modul tableWrapper
import pgsqlDAO
import mysqlDAO
import xmlDAO
class TableWrapper:
"""dbwrapper"""
def __init__(self):
"""init"""
def connect(self,DbType,Host,Db,User):
if DbType=='PgSQL':
self.dbWrapper=pgsqlDAO.PgSqlDAO()
self.dbWrapper.connect(Host,Db,User)
if DbType=='MySQL':
self.dbWrapper=mysqlDAO.MySqlDAO()
self.dbWrapper.connect(Host,Db,User)
if DbType=='XML':
self.dbWrapper=xmlDAO.XmlDAO()
def getTableNameList(self):
return self.dbWrapper.getTableNameList()
def getTableColumnsList(self):
return self.dbWrapper.getTableColumnsList()
def getTableColumnsData(self):
return self.dbWrapper.getTableColumnsData()
def insertTableColumnsData(self,colList,valueList):
self.dbWrapper.insertTableColumnsData(colList,valueList)
def close(self):
self.dbWrapper.close()
Code: Alles auswählen
#!/usr/bin/env python
#Modul pgsqlDAO
#PostgreSQL WIN dbAPI
import pyPgSQL.PgSQL
class PgSqlDAO:
def __init__(self):
"""..."""
def connect(self,Host,Db,User):
self.con=pyPgSQL.PgSQL.connect(host=Host,database=Db,user=User)
def getTableNameList(self):
cur=self.con.cursor()
sql="""SELECT tablename
FROM pg_tables
WHERE tablename !~* 'pg_*' and tablename !~* 'sql_*';"""
cur.execute(sql)
pgresult=cur.fetchall()
tableNameList=[]
for i in pgresult:
tableNameList.append(i[0])
return tableNameList
def getTableColumnsList(self):
cur=self.con.cursor()
sql="""SELECT a.attnum, a.attname AS field, t.typname AS type,
a.attlen AS length, a.atttypmod AS length_var,
a.attnotnull AS not_null, a.atthasdef as has_default
FROM pg_class c, pg_attribute a, pg_type t
WHERE c.relname = 'tfoo'
AND a.attnum > 0
AND a.attrelid = c.oid
AND a.atttypid = t.oid
ORDER BY a.attnum;"""
cur.execute(sql)
pgresult=cur.fetchall()
tableColList=[]
for i in pgresult:
tableColList.append(i[1])
return tableColList
def getTableColumnsData(self):
cur=self.con.cursor()
sql="""SELECT * from tfoo;"""
cur.execute(sql)
pgresult=cur.fetchall()
return pgresult
def insertTableColumnsData(self,colList,valueList):
cur=self.con.cursor()
columns = colList
cols = ", ".join(columns)
value_placeholders = ", ".join(["%s"] * len(columns))
values = valueList
sql = """insert into tfoo (%(cols)s)
values (%(value_placeholders)s)""" % locals()
cur.execute(sql, values)
self.con.commit()
def close():
self.con.close()
Code: Alles auswählen
#!/usr/bin/env python
#Modul xmlDAO
#Pythoninternes xmlAPI
import xml.dom.minidom
class XmlDAO:
def __init__(self):
""" --- """
self.filename="db.xml"
self.doc = xml.dom.minidom.parse(self.filename)
tables=[]
mapping = {}
def getTableNameList(self):
tableNameList=[]
for i in self.doc.getElementsByTagName("table"):
name=i.getAttribute("name")
tableNameList.append(name)
return tableNameList
def getTableColumnsList(self):
for table in self.doc.getElementsByTagName("table"):
if table.getAttribute("name")=='t1':
rows=table.getElementsByTagName("row")
if len(rows):
colList=[]
for col in rows[0].childNodes:
if col.nodeType==col.ELEMENT_NODE:
colList.append(col.tagName)
return colList
def getTableColumnsData(self):
for table in self.doc.getElementsByTagName("table"):
if table.getAttribute("name")=='t1':
rows=table.getElementsByTagName("row")
colList=self.getTableColumnsList()
datalist=[]
for i in range(len(rows)):
list=[]
datalist.append(list)
rowid=-1
for row in rows:
rowid=rowid+1
for name in colList:
for item in row.getElementsByTagName(name):
item.normalize()
datalist[rowid].append(item.firstChild.data)
return datalist
def insertTableColumnsData(self,colList,valueList):
xmlstr='<row>'
for i in range(len(colList)):
xmlstr = xmlstr + "<" + colList[i] + ">" + valueList[i] + "</" + colList[i] + ">"
rowxml = xmlstr + "</row>\n"
rowMiniDOM=xml.dom.minidom.parseString(rowxml)
rowDOM=rowMiniDOM.documentElement
for table in self.doc.getElementsByTagName("table"):
if table.getAttribute("name")=='t1':
table.appendChild(rowDOM)
#xml_save
xmlfile=open(self.filename,'w')
xmlfile.write(self.doc.toxml())
xmlfile.close()
Code: Alles auswählen
<?xml version="1.0" ?>
<xmldb>
<table name="t1">
<row><id>101</id><username>rolgal</username><usertype>Poweruser</usertype></row>
<row><id>102</id><username>Leonidas</username><usertype>Poweruser</usertype></row>
<row><id>103</id><username>Olliminatore</username><usertype>User</usertype></row>
<row><id>104</id><username>tabellar</username><usertype>User</usertype></row>
</table>
<table name="t2">
<row><titel>Python und XML</titel><author>xyz</author></row>
</table>
</xmldb>
hallo tabellar,
sieht ja echt gut aus,....bin platt
ich krieg leider keine benachrichtigungen, wenn zu diesem thread antworten geschrieben werden, war also glücklicher zufall, dein post gesehen zu haben, keine ahnung was da los ist.
grüße
rolgal
sieht ja echt gut aus,....bin platt
ich krieg leider keine benachrichtigungen, wenn zu diesem thread antworten geschrieben werden, war also glücklicher zufall, dein post gesehen zu haben, keine ahnung was da los ist.
grüße
rolgal
Schön, wenn es Dir gefällt. Hättest Du nicht Lust die "mysqlDAO" zu machen? Ich habe leider keinen Zugriff von meinem WIN Notey auf meinen Gentoo Linux Rechner, auf dem MySQL aber wunderbar läuft. Auch Rechte setzen bringt nichts, hm, keine Ahnung warum der connect auf den MySQL Server von externen Rechnern nicht funktioniert .rolgal hat geschrieben:hallo tabellar,
sieht ja echt gut aus,....bin platt
Gruss Tabellar
hi tabellar,
ich werde gern das mysqlDAO machen,
bis bald oder auch etwas länger wenn es fuchst
rolgal
ich werde gern das mysqlDAO machen,
bis bald oder auch etwas länger wenn es fuchst
rolgal
hallo tabellar,
also ich habe mich soweit ich konnte mit deinem code auseinandergesetzt und mir ist da einiges aufgefallen, was wir besprechen sollten,....
1. tablewrapper: import anweisungen würde ich hier machen:
es ist nicht so sinnvoll alle schnittstellen automatisch zu importieren.
2. db_client, es braucht meiner meinung nach auf jeden fall auch die ermitllung der aktuellen tabelle, sonst wird es schwierig die daten auszugeben, in deinem beispiel geht das nur weil du eine konstante verwendest:
tfoo ist gemeint
daher:
die tabelle self.db_table muss für diverse anweisungen übergeben werden.
mein nicht fertiges mysqlDAO sieht momentan so aus:
prinzipiell arbeite ich ja auch noch an der alten fassung, die bereits tabellen wechseln kann, es scheint sinnvoll den db_client, das hauptfenster so zu gestalten:
auch habe ich mir ueberlegt gewisse dinge vielleicht doch im konstruktor zu setzen, z.b. im tablewrapper den datenbanktyp
das mit der übergabe von attributen ist net so einfach, will man dein ziel umsetzen einen uni db client zu haben.
die auszuführende anweisung (action) und die betreffende tabelle (self.db_table) müssen hier übergeben werden, aber woher nehmen???
die tabelle ist klar, aber die action, da hirne ich noch
so, das waren mal die wichtigsten überlegungen für den moment, ich mach mal weiter,
bis bald,
wollte einfach auch mal ein lebenszeichen geben,
rolgal
also ich habe mich soweit ich konnte mit deinem code auseinandergesetzt und mir ist da einiges aufgefallen, was wir besprechen sollten,....
1. tablewrapper: import anweisungen würde ich hier machen:
Code: Alles auswählen
if DbType=='MySQL':
import mysqlDAO
self.dbWrapper=mysqlDAO.MySqlDAO()
self.dbWrapper.connect(Host,User,Db,Passwd)
2. db_client, es braucht meiner meinung nach auf jeden fall auch die ermitllung der aktuellen tabelle, sonst wird es schwierig die daten auszugeben, in deinem beispiel geht das nur weil du eine konstante verwendest:
Code: Alles auswählen
def getTableColumnsData(self):
cur=self.con.cursor()
sql="""SELECT * from tfoo;"""
cur.execute(sql)
pgresult=cur.fetchall()
daher:
Code: Alles auswählen
def __init__(self):
""",host,user,db,db_table,passwd=''"""
self.root=Tk()
self.root.wm_geometry('+20+20')
self.prepare()
self.root.title("Hauptfenster")
#instantiierung DbWrapper...
self.tablewrapper=tableWrapper.TableWrapper()
# Manuelle Datenbankauswahl via Angabe
# des Datenbanktyps: (später durch Dialogauswahl...)
# PgSQL
# MySQL
# XML
self.tablewrapper.connect('MySQL','localhost','ein user','eine db','ein passwort')
#tabellen ermitteln
self.db_tables=self.tablewrapper.getTableNameList()
#erste tabelle als default verwenden, später kann diese variable ueber das auswahlfenster neu gesetzt werden
self.db_table=self.db_tables[0]
self.cols_names=self.tablewrapper.getTableColumnsList(self.db_table)
die tabelle self.db_table muss für diverse anweisungen übergeben werden.
mein nicht fertiges mysqlDAO sieht momentan so aus:
Code: Alles auswählen
import MySQLdb
from _mysql_exceptions import *
class MySqlDAO:
def __init__(self):
"""..."""
def connect(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 getTableNameList(self):
cur=self.conn.cursor()
cur.execute("show tables from %s"%self.db)
result=cur.fetchall()
tableNameList=[]
for i in result:
tableNameList.append(i[0])
return tableNameList
def getTableColumnsList(self,db_table):
cur=self.conn.cursor()
cur.execute("show columns from %s"%db_table)
result=cur.fetchall()
tableColList=[]
for i in result:
if 'auto_increment' not in i:
tableColList.append(i[0])
return tableColList
def getTableColumnsData(self,action,db_table):
action=action%db_table
cursor=self.conn.cursor()
cursor.execute(action)
result=cursor.fetchall()
cursor.close()
return result
def insertTableColumnsData(self,action):
cursor=self.conn.cursor()
cursor.execute(action)
cursor.close()
def close(self):
self.conn.close()
Code: Alles auswählen
class HauptFenster(Fenster):
lt="Ausgabe"
def __init__(self,host,user,db,passwd=''):
self.root=Tk()
self.root.wm_geometry('+20+20')
self.prepare()
self.root.title("Hauptfenster")
self.database=MySqlApi(host,user,db,passwd)
if self.database.table_number>1:
auswahl=AuswahlFenster(self,self.root,self.database.db_tables)
self.choice=StringVar()
self.db_table=self.database.db_table
self.db_table_cols=self.database.db_table
self.cols_names=self.database.cols_names
self.s_cols_names=", ".join(self.cols_names)
self.li_1width=len(self.cols_names)*12
# das ist es um was es geht, frames, die spaeter einzeln neu gesetzt werden koennen.
self.frame_1=Frame(self.root)
self.frame_1.grid(row=2,column=0,columnspan=2)
self.set_frame_1()
self.frame_2=Frame(self.root)
self.frame_2.grid(row=5,column=0,columnspan=2)
self.set_frame_2()
self.frame_3=Frame(self.root)
self.frame_3.grid(row=9,column=1)
self.set_frame_3()
def set_frame_1(self):
self.scb_v=Scrollbar(self.frame_1, orient="vertical")
self.scb_h=Scrollbar(self.frame_1, orient="horizontal")
self.li_1=Listbox(self.frame_1,
width=self.li_1width,height=8,
yscrollcommand=self.scb_v.set,
xscrollcommand=self.scb_h.set)
self.scb_v["command"]=self.li_1.yview
self.scb_h["command"]=self.li_1.xview
self.li_1.grid(row=3,column=0,
columnspan=2,
padx=self.a_x,pady=self.a_y)
self.scb_v.grid(row=3,column=2,
padx=self.a_x,pady=self.a_y)
self.scb_h.grid(row=4,column=0,
columnspan=2,
padx=self.a_x,pady=self.a_y)
def set_frame_2(self):
b_1=Button(self.frame_2,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=6,column=0,
padx=self.a_x,pady=self.a_y)
b_2=Button(self.frame_2,width=self.b,
text="Loeschen",command=self.ask)
b_2.grid(row=6,column=1,
padx=self.a_x,pady=self.a_y)
b_3=Button(self.frame_2,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,self.choice.get()))))
b_3.grid(row=7,column=0,
padx=self.a_x,pady=self.a_y)
b_4=Button(self.frame_2,width=self.b,text="Eingabe",
command=lambda:
EingabeFenster
(self.frame_2,self.database,
self.db_table,self.cols_names,
self.root.winfo_width()))
b_4.grid(row=7,column=1,
padx=self.a_x,pady=self.a_y)
b_5=Button(self.frame_2,width=self.b,text="Suchen",
command=lambda:
SuchFenster
(self,self.root,self.database,self.db_table))
b_5.grid(row=8,column=0,
padx=self.a_x,pady=self.a_y)
b_6=Button(self.frame_2,width=self.b,text="Bearbeiten",
command=lambda:
BearbeitungsFenster
(self.root,self.database,
self.db_table,self.cols_names,
self.li_1.get("active"),
self.root.winfo_width()))
b_6.grid(row=8,column=1,padx=self.a_x,pady=self.a_y)
def set_frame_3(self):
for i in range(len(self.cols_names)):
self.rb=Radiobutton(self.frame_3,text=self.cols_names[i],
value=self.cols_names[i],
variable=self.choice)
self.rb.grid(row=i+9,column=1,
padx=self.a_x,pady=self.a_y)
if i==0:
self.rb.select()
self.list_data(result=self.database.get_data("select %s from %s"%(self.s_cols_names,self.db_table)))
#usw.
das mit der übergabe von attributen ist net so einfach, will man dein ziel umsetzen einen uni db client zu haben.
Code: Alles auswählen
b_1=Button(self.root,width=self.b,text="Alle Daten",
command=lambda:
self.list_data(self.tablewrapper.getTableColumnsData(action,self.db_table))
die tabelle ist klar, aber die action, da hirne ich noch
so, das waren mal die wichtigsten überlegungen für den moment, ich mach mal weiter,
bis bald,
wollte einfach auch mal ein lebenszeichen geben,
rolgal
Code: Alles auswählen
Hi Rolgal,
schön, dass es auch hier ein wenig weiter geht...
GUI Ziele:
- DB Auswahl
- Connect
- Tabellenauswahl
- Ansichtsfenster in Tabellenform
Gruss Tabellar
schön, dass es auch hier ein wenig weiter geht...
Klar, das ist natürlich so besser.rolgal hat geschrieben:1. tablewrapper: import anweisungen würde ich hier machen:
es ist nicht so sinnvoll alle schnittstellen automatisch zu importieren.Code: Alles auswählen
if DbType=='MySQL': import mysqlDAO self.dbWrapper=mysqlDAO.MySqlDAO() self.dbWrapper.connect(Host,User,Db,Passwd)
In der TableWrapper Klasse war die Methode "getTableNameList()" ja schon vorgesehen und implementiert. Ich hab den Tabellennamen einfach fix verdrahtet, weil der Auswahldialog dazu noch nicht da war. Die Lösung mit "self.db_tables[0] ist natürlich gleich viel eleganter flexibler.rolgal hat geschrieben:2. db_client, es braucht meiner meinung nach auf jeden fall auch die ermitllung der aktuellen tabelle, sonst wird es schwierig die daten auszugeben, in deinem beispiel geht das nur weil du eine konstante verwendest:
tfoo ist gemeintCode: Alles auswählen
def getTableColumnsData(self): cur=self.con.cursor() sql="""SELECT * from tfoo;""" cur.execute(sql) pgresult=cur.fetchall()
daher:
die tabelle self.db_table muss für diverse anweisungen übergeben werden.Code: Alles auswählen
... self.db_tables=self.tablewrapper.getTableNameList() #erste tabelle als default verwenden, später kann diese variable ueber das auswahlfenster neu gesetzt werden self.db_table=self.db_tables[0] ---
Super, wenn die MySqlDAO bald fertig ist. Dann ist eine reine GUI Entwicklung möglich... Hast Du vielleicht schon einen Screenshot von deiner neuen GUI (Tabellenauswahl) ?rolgal hat geschrieben:mein nicht fertiges mysqlDAO sieht momentan so aus:
Code: Alles auswählen
import MySQLdb from _mysql_exceptions import * class MySqlDAO: def __init__(self): """...""" def connect(self,host,user,db,passwd=''): ...
GUI Ziele:
- DB Auswahl
- Connect
- Tabellenauswahl
- Ansichtsfenster in Tabellenform
Schön, mich freut es, wenn es hier so ein paar Projekte gibt... Meine Augen sind auf jeden Fall auch in Deinem Projekt ...rolgal hat geschrieben:so, das waren mal die wichtigsten überlegungen für den moment, ich mach mal weiter, bis bald, wollte einfach auch mal ein lebenszeichen geben,
Gruss Tabellar
für folgendes problem nachstehender lösungsvorschlag, müsste man aber dann in allen DAOs so machen
im konstruktor des mysqlDAO folgendes dictionary:
die methode getTableColumnsData:
im db_client wären also die folgende änderungen notwendig:
funktionieren tut es
ausserdem brauchen wir die spaltennamen 2mal, einmal für die gui, dem frontend und einmal für dateioperationen,
ich will keine id's u.ä. in der gui, schon gar nicht wenn sie automatisch hochgezählt werden, gerade für das bearbeitungsfenster, eingabefenster ist das sonst ein problem
mfg
rolgal
das mit der übergabe von attributen ist net so einfach, will man dein ziel umsetzen einen uni db client zu haben.die auszuführende anweisung (action) und die betreffende tabelle (self.db_table) müssen hier übergeben werden, aber woher nehmen???Code: Alles auswählen
b_1=Button(self.root,width=self.b,text="Alle Daten", command=lambda: self.list_data(self.tablewrapper.getTableColumnsData(action,self.db_table))
im konstruktor des mysqlDAO folgendes dictionary:
Code: Alles auswählen
def __init__(self):
self.actions={"all":"select * from %s","sort":"select %s from %s order by %s"}
Code: Alles auswählen
def getTableColumnsData(self,a_type,*values):
action=self.actions[a_type]
for element in values:
action=action%element
cursor=self.conn.cursor()
cursor.execute(action)
result=cursor.fetchall()
cursor.close()
return result
Code: Alles auswählen
b_1=Button(self.root,width=self.b,text="Alle Daten",
command=lambda:
self.list_data(self.tablewrapper.getTableColumnsData("all",(self.db_table))))
b_1.grid(row=4,column=0,
padx=self.a_x,pady=self.a_y)
#...b_2 interessiert jetzt keinen
b_3=Button(self.root,width=self.b,text="Sortieren",
command=lambda:
self.list_data(self.tablewrapper.getTableColumnsData("sort",(self.s_cols_names,
self.db_table,
self.choice.get()))))
b_3.grid(row=5,column=0,
padx=self.a_x,pady=self.a_y)
ausserdem brauchen wir die spaltennamen 2mal, einmal für die gui, dem frontend und einmal für dateioperationen,
ich will keine id's u.ä. in der gui, schon gar nicht wenn sie automatisch hochgezählt werden, gerade für das bearbeitungsfenster, eingabefenster ist das sonst ein problem
mfg
rolgal
Hi Rolgal,
ich hab auch ein bisschen weiter gemacht... :
Du siehst, ich habe die "import" Anweisung in die if-condition gesteckt. Bei den Methoden siehst du jetzt ausserdem, dass überall entsprechende Argumente (tableName, etc. ) übergeben werden können. Sprich, keine "fixe" Tabellenverdrahtung mehr.
Hier ist der code für die "Datenbank- und Tabellenauswahl" im Konstruktor der "Hauptfenster" Klasse. Die Auswahl der XML DB ist jetzt auch dynamisch (allerdings hat sich die xmlDAO auch entspr. verändert).
Hm, ich bin nicht so der Freund von einzelnen SQL Commands in Dictionarys etc. Ich finde, dass die Übersichtlichkeit im Programm verloren geht. Ich persönlich finde es schöner, wenn sich die Funktionalität in den einzelnen Methodenaufrufen wiederspiegelt. Ausserdem haben wir bei der XML DB keine SQL Commands. Also wäre hier das Pendant zu deinem SQL-Dict eine neue Methode in der TableWrapper Class:
Ich persönlich würde diese Form vorziehen, zumal es auch eine Art "Black Box" darstellt. ich warte aber mal, was du dazu meinst ... Ein nächster schöner Schritt wäre es, im DB-Client per Dialog die entsprechende Datenbank und die Tabellen auszuwählen...
Gruss Tabellar
PS: Vielleicht können wir dann bald den DB-Client für den "SQLator" verwenden ...
ich hab auch ein bisschen weiter gemacht... :
Code: Alles auswählen
class TableWrapper:
"""dbwrapper"""
def __init__(self):
"""init"""
def connect(self,DbType,Host,Db,User):
if DbType=='PgSQL':
import pgsqlDAO
self.dbWrapper=pgsqlDAO.PgSqlDAO()
self.dbWrapper.connect(Host,Db,User)
if DbType=='MySQL':
import mysqlDAO
self.dbWrapper=mysqlDAO.MySqlDAO()
self.dbWrapper.connect(Host,Db,User)
if DbType=='XML':
import xmlDAO
self.dbWrapper=xmlDAO.XmlDAO()
self.dbWrapper.connect(Host,Db,User)
def getTableNameList(self):
return self.dbWrapper.getTableNameList()
def getTableColumnsList(self,tableName):
return self.dbWrapper.getTableColumnsList(tableName)
def getTableColumnsData(self,tableName):
return self.dbWrapper.getTableColumnsData(tableName)
def insertTableColumnsData(self,tableName,colList,valueList):
self.dbWrapper.insertTableColumnsData(tableName,colList,valueList)
def close(self):
self.dbWrapper.close()
Code: Alles auswählen
#Instantiierung DbWrapper...
self.tablewrapper=tableWrapper.TableWrapper()
#Auswahl der Datenbank
self.tablewrapper.connect('XML','10.2.0.1','db.xml','userName')
#self.tablewrapper.connect('PgSQL','10.2.0.1','dbname','useName')
#Festlegung der Tabelle
self.db_tables=self.tablewrapper.getTableNameList()
self.db_table=self.db_tables[0]
self.cols_names=self.tablewrapper.getTableColumnsList(self.db_table)
rolgal hat geschrieben:<snip> ... im konstruktor des mysqlDAO folgendes dictionary:
</snip>Code: Alles auswählen
def __init__(self): self.actions={"all":"select * from %s","sort":"select %s from %s order by %s"}
Hm, ich bin nicht so der Freund von einzelnen SQL Commands in Dictionarys etc. Ich finde, dass die Übersichtlichkeit im Programm verloren geht. Ich persönlich finde es schöner, wenn sich die Funktionalität in den einzelnen Methodenaufrufen wiederspiegelt. Ausserdem haben wir bei der XML DB keine SQL Commands. Also wäre hier das Pendant zu deinem SQL-Dict eine neue Methode in der TableWrapper Class:
Code: Alles auswählen
def getTableColumnsDataSort(self,tableName,colNames,orderChoice):
return self.dbWrapper.getTableColumnsDataSort(tableName,colNames,orderChoice)
Gruss Tabellar
PS: Vielleicht können wir dann bald den DB-Client für den "SQLator" verwenden ...
hallo tabellar,
wäre interessant zu wissen, was blackjack, leonidas u.a. python-gurus dazu meinen.
davor sollten wir uns einigen wie wir obigen punkt lösen, dann häng ich mich wieder in die tasten, zeitlich wird es bei mir nämlich bald wieder besser
liebe grüße
rolgal
man könnte das dictionary in eine datei auslagern und über pickle laden, irgendwie gefällt es mir besser wenn es für alle funktionen, die schlussendlich dasselbe tun, also z.b. lesen, es eine methode gibt. ich muss dir aber ehrlich sagen, dass das eine bauchsache ist. ich kann das nicht wirklich argumentieren.Hm, ich bin nicht so der Freund von einzelnen SQL Commands in Dictionarys etc. Ich finde, dass die Übersichtlichkeit im Programm verloren geht.
wäre interessant zu wissen, was blackjack, leonidas u.a. python-gurus dazu meinen.
ich möchte zuerst wieder die ursprgl. funktionalität herstellen.Ich persönlich würde diese Form vorziehen, ich warte aber mal, was du dazu meinst ... Wink Ein nächster schöner Schritt wäre es, im DB-Client per Dialog die entsprechende Datenbank und die Tabellen auszuwählen...
davor sollten wir uns einigen wie wir obigen punkt lösen, dann häng ich mich wieder in die tasten, zeitlich wird es bei mir nämlich bald wieder besser
liebe grüße
rolgal
Hi rolgal,
ich hätte zu dem Thema mal folgenden guten Link. und hier auch noch.
Thema hier ist die parametrisierte Form von cursor.execute und die Vermeidung von "SQL-Injection-Angriffen" (quoten der Input Werte durch den Escape-Mechanismus der DB-API). Solange wir diese Dinge bei unseren SQL Commands der Form beachten, sind wir in der schlussendlichen Implementierung frei.
Gruassle Tabellar
ich hätte zu dem Thema mal folgenden guten Link. und hier auch noch.
Thema hier ist die parametrisierte Form von cursor.execute und die Vermeidung von "SQL-Injection-Angriffen" (quoten der Input Werte durch den Escape-Mechanismus der DB-API). Solange wir diese Dinge bei unseren SQL Commands der Form
Code: Alles auswählen
"select %s from %s order by %s"
Ja, gute Idee, vielleicht meldet sich ja der ein oder andere dazu ... ?rolgal hat geschrieben:...man könnte das dictionary in eine datei auslagern und über pickle laden, irgendwie gefällt es mir besser wenn es für alle funktionen, die schlussendlich dasselbe tun, also z.b. lesen, es eine methode gibt. ich muss dir aber ehrlich sagen, dass das eine bauchsache ist. ich kann das nicht wirklich argumentieren.
wäre interessant zu wissen, was blackjack, leonidas u.a. python-gurus dazu meinen.
Gut. Eine gemeinsame Lösung, die auch noch OPTIMAL im Sinne der DB Abfrage ist, wäre natürlich der Hit.... Das sollten wir doch schaffen, oder ???rolgal hat geschrieben:ich möchte zuerst wieder die ursprgl. funktionalität herstellen. davor sollten wir uns einigen wie wir obigen punkt lösen, dann häng ich mich wieder in die tasten, zeitlich wird es bei mir nämlich bald wieder besser
Gruassle Tabellar
hi tabellar,
das heisst nachstehende funktion passt so net, weil es nicht im execute geschieht? ganz blick ich bei der problematik net durch, habe aber in der eile die links nur überflogen.
kannst mir mal schnell in 2, 3 sätzen das verdeutlichen?
seit dem halte ich mich dran
abgesehen davon gibts hier keine krise, sondern ein großes teil, das halt nur in kleinen schritten zusammengesetzt werden kann
grüße
rolgal
ich hätte zu dem Thema mal folgenden guten Link. und hier auch noch.
Thema hier ist die parametrisierte Form von cursor.execute und die Vermeidung von "SQL-Injection-Angriffen" (quoten der Input Werte durch den Escape-Mechanismus der DB-API). Solange wir diese Dinge bei unseren SQL Commands der Form
Python-Code:
"select %s from %s order by %s"
beachten, sind wir in der schlussendlichen Implementierung frei.
das heisst nachstehende funktion passt so net, weil es nicht im execute geschieht? ganz blick ich bei der problematik net durch, habe aber in der eile die links nur überflogen.
kannst mir mal schnell in 2, 3 sätzen das verdeutlichen?
Code: Alles auswählen
def getTableColumnsData(self,a_type,*values):
action=self.actions[a_type]
for element in values:
action=action%element
cursor=self.conn.cursor()
cursor.execute(action)
result=cursor.fetchall()
cursor.close()
return result
ein freund sagte in einer meiner krisen mal zu mir: aufgeben tut man briefe...Gut. Eine gemeinsame Lösung, die auch noch OPTIMAL im Sinne der DB Abfrage ist, wäre natürlich der Hit.... Razz Das sollten wir doch schaffen, oder Wink ???
seit dem halte ich mich dran
abgesehen davon gibts hier keine krise, sondern ein großes teil, das halt nur in kleinen schritten zusammengesetzt werden kann
grüße
rolgal
-
- Python-Forum Veteran
- Beiträge: 16025
- Registriert: Freitag 20. Juni 2003, 16:30
- Kontaktdaten:
Solange die DB Module pyformat nutzen, wenn es aber ein anderer paramstyle ist könnte das wiederrum Probleme bereiten.tabellar hat geschrieben:Thema hier ist die parametrisierte Form von cursor.execute und die Vermeidung von "SQL-Injection-Angriffen" (quoten der Input Werte durch den Escape-Mechanismus der DB-API). Solange wir diese Dinge bei unseren SQL Commands der Formbeachten, sind wir in der schlussendlichen Implementierung frei.Code: Alles auswählen
"select %s from %s order by %s"
Ist schon nett als Guru bezeichnet zu werden, jedoch bin ich mit Datenbanken nicht so vertraut, also solltet ihr da besser auf die Meinung von BlackJack warten, bevor ich hier irgendwelchen Schrott erzähle.tabellar hat geschrieben:Ja, gute Idee, vielleicht meldet sich ja der ein oder andere dazu ... ?rolgal hat geschrieben:wäre interessant zu wissen, was blackjack, leonidas u.a. python-gurus dazu meinen.
Ich persönlich würde aber zur "Black Box"-Variante von Tabellar tendieren, schaut mir irgendwie "sauberer" aus (obwohl die Funktionsnamen etwas kürzer sein dürften *g*).
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice