Projekterstellung mit GUI

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Guten Tag,

ich habe folgendes vor. Es geht um eine Datenbank für einen Sportverein. Die Datenbank ist fertig und läuft auf einem MYSQL Server. In der Datenbank sollen die Schützen erfasst werden, sobald diese einen Stand betretten und sich an einem Gerät anmelden. hier würde ich gern mit RFID und einem Raspberry arbeiten. Der User soll dann nach Anmeldung die Möglichkeit bekommen, sich seinen Platz auszuwählen. Das soll dann in die Datenbank geschrieben werden.
Ist der Schütze fertig soll er sich wieder mit RFID und der Funktion abmelden, von dem Stand abmelden.

Aktuell hat der Verein 5 Stände auf denen dann solche Geräte zum Einsatz kommen sollen. Das Gerät muss dann seinen Stand fest kennen, bzw über ein Merkmal des Gerätes diesen Ort mitteilen. Also wenn der Schütze auf dem 25 Meter Stand ist, soll das Endgerät das wissen und es soll nicht nochmal aus wählbar sein.

Per PHP und HTML habe ich bereits das Szenario soweit programmiert. Aber wie sollte ich am besten Starten, dass in Python umzusetzen? Ist das realisierbar so wie ich es mir vorstelle?
Bastel grade bissl rum mit pyQt.... Aber das ist schon alles erstmal sehr abstrakt.


Liebe Grüße und Danke für die IDeen.
Benutzeravatar
__blackjack__
User
Beiträge: 13069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@matze1708: Abstrakt ist ein gutes Stichwort. Was ist denn jetzt die konkrete Frage?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Die eigentliche Frage wäre,

lässt sich das so umsetzten und wo fange ich am besten an?
Benutzeravatar
__blackjack__
User
Beiträge: 13069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@matze1708: Die Beschreibung ist ja recht unkonkret. Etwas in der Richtung lässt sich sicher umsetzen, und anfangen kann man am Anfang. ;-) Also mit einer detaillierteren Anforderungsanalyse.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Ich versuche es mal .... weiss aber nicht ob es genug detaliert ist.


Also: Es handelt sich um ein Schiessbuch welches Digital werden soll. Dazu dachte ich, dass ich Raspberrys nehme mit Touch Display und einem RFID Reader.

Auf jedem der 5 Stände soll so ein Raspberry hängen. Die Schützen haben hierzu RFID Karten oder Anhänger.....
Ist der Schütze nun auf dem Stand muss er sich an de Gerät mit seiner Karte anmelden und auf einer Auswahl seinen Platz eintragen.
Damit soll dann ein Tabellen eintrag erzeugt werden.

Ist der Schütze fertig, geht er wieder an das Gerät und es wird in der Tabelle ein Eintrag erzeugt für das abmelden.


DB seitig habe ich das

tbl_Benutzer
tbl_Karten
tbl_Kaliber
tbl_Stand
tbl_Schiessbuch

Ein Benutzer kann X Karten haben. In der Tabelle tbl_karten, kann man KArten aktivieren und deaktiveren.
Benutzer können gesperrt werden etc.
In tbl_Kaliber, stehen die Kaliber die Geschossen werden können
in tbl_Stände, sind all unsere Stände hinterelgt
tbl_Schiessbuch ist eine Zusammenfassung über 1 zu n Beziehungen zu den vor genannten Tabellen.

Aber das Thema mit den Abfragen, Select, Insert etc bekomme ich hin.

Mir fehlt es nur am Python. und vorallem an der Grafischen Oberfläche.

Da kämpfe ich seit Montag mir PyQt etc.
Benutzeravatar
__blackjack__
User
Beiträge: 13069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@matze1708: Naja, das ist halt immer noch kein konkretes Problem was man irgendwie beantworten könnte.

So ganz allgemeine Anmerkungen: Der `tbl_`-Präfix ist unnötig. Bei Tabellennamen würde ich Einzahl verwenden, genau wie bei Klassen oder im ER/UML-Diagramm für die Datenbankstruktur. Auf jeden Fall aber konsistent, und nicht mal Einzahl (z.B. Stand) und mal Mehrzahl (z.B. Karten).

Für Datenbankzugriffe nehme ich fast immer SQLAlchemy als Zwischenschicht, meistens auch das ORM davon.

Die GUI wird ja erst wirklich interessant wenn die Programmlogik da ist. Das sollte man getrennt von der GUI machen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Für Datenbankzugriffe nehme ich fast immer SQLAlchemy als Zwischenschicht, meistens auch das ORM davon.

Die GUI wird ja erst wirklich interessant wenn die Programmlogik da ist. Das sollte man getrennt von der GUI machen.
Genau das Hilft mir.

Bin nämlich am rum Doktoren mit Qt Designer/Creator

In der Hoffnung ich bekomme da was hin, hätte dann da parallel die Logik miteibgebaut.

Für SQL habe ich aktuell Mysqldb genutzt mit erfolg.
Und über pyqt bin ich auch an die DB gekommen.
QMysql

Dann hört es aber aktuell auch auf.

Weil ich gern ein festes Fenster hätte, das auf RFID eingabe wartet und dann zum nächsten Springt.


Schaue ich mir mal deine beiden Dinge an und blende mal die GUI aus.
Dachte es macht Sinn direkt mit GUI
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Hallo,

ich habe nun mal etwas rudimentäres entworfen.

Lässt sich das jetzt hier schon etwas besser Strukturieren und abkürzen?

Kann ich den Connection Part auch in eine Funktion schreiben, um die nicht immer wieder aufzurufen?

Geil wäre halt ne richtige Grafik Oberfläche.


Einiges an Logik werde ich noch einbauen. Damit der Ablauf einfacher wird.

Achso, bei Umlauten ß,ö etc werden mir ? ausgeben. Habe da mit utf8 etc mal rumgespielt, kam aber immer das gleiche raus.

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: iso-8859-1 -*-
# -*- encoding: iso-8859-15 -*-
# SchuetzeAnlegen.py 


import sys
import RPi.GPIO as GPIO
import MFRC522
import signal
import MySQLdb
import datetime



print("Schiessbuch")
print
print("Bitte erfasse deine Daten!")
print

def BenutzerAnzeigen():
    print
    try: 
        mydb = MySQLdb.connect(host="10.100.124.14", user="XXX", passwd="XXX", db="Schiessbuch", port=3307)
 
        mycursor = mydb.cursor(MySQLdb.cursors.DictCursor)
 
        
        with mydb:
        
            mycursor.execute("Select tbl_Benutzer.ID, tbl_Benutzer.UName, tbl_Benutzer.UVorname FROM tbl_Benutzer INNER JOIN tbl_Karten ON tbl_Benutzer.ID = tbl_Karten.UserID") 
        
            rows = mycursor.fetchall()

        for row in rows:
            print row["ID"], row["UName"], row["UVorname"]
            
            
 
    except MySQLdb.Error as error : 
        mydb.rollback() 
        print("Failed to insert into MySQL table {}".format(error)) 
 
    finally: 
        #closing database connection. 
        if(mydb.ping()): 
            mycursor.close() 
            mydb.close() 
            print("MySQL connection is closed")     
    

BenutzerAnzeigen()


try:
    print
    var_User = int(input("Bitte deine User ID eingeben: "))
except:
    print("Fehler: Keine Zahl eingegeben.")
    sys.exit()


def StandAnzeigen():
    print
    try: 
        mydb = MySQLdb.connect(host="10.100.124.14", user="XXX", passwd="XXX", db="Schiessbuch", port=3307)
 
        mycursor = mydb.cursor(MySQLdb.cursors.DictCursor)
 
        
        with mydb:
        
            mycursor.execute("Select ID, StandLang From tbl_Stand") 
        
            rows = mycursor.fetchall()

        for row in rows:
            print row["ID"], row["StandLang"]
            
            
 
    except MySQLdb.Error as error : 
        mydb.rollback() 
        print("Failed to insert into MySQL table {}".format(error)) 
 
    finally: 
        #closing database connection. 
        if(mydb.ping()): 
            mycursor.close() 
            mydb.close() 
            print("MySQL connection is closed") 


StandAnzeigen()


try:
    print
    var_StandID = int(input("Bitte Stand eingeben: "))
except:
    print("Fehler: Keine Zahl eingegeben.")
    sys.exit()




def KaliberAnzeigen():
    print
    try: 
        mydb = MySQLdb.connect(host="10.100.124.14", user="XXX", passwd="XXX", db="Schiessbuch", port=3307)
 
        mycursor = mydb.cursor(MySQLdb.cursors.DictCursor)
 
        
        with mydb:
        
            mycursor.execute("Select ID, KaliberLang From tbl_Kaliber") 
        
            rows = mycursor.fetchall()

        for row in rows:
            print row["ID"], row["KaliberLang"]
           
 
    except MySQLdb.Error as error : 
        mydb.rollback() 
        print("Failed to insert into MySQL table {}".format(error)) 
 
    finally: 
        #closing database connection. 
        if(mydb.ping()): 
            mycursor.close() 
            mydb.close() 
            print("MySQL connection is closed") 


KaliberAnzeigen()


try:
    print
    var_KaliberID = int(input("Bitte Kaliber eingeben: "))
except:
    print("Fehler: Keine Zahl eingegeben.")
    sys.exit()


#Anfrage Platz
print
try:
    var_Platz = int(input("Auf welchem Stand schiesst du?: "))
except:
    print("Fehler: Keine Zahl eingegeben.")
    sys.exit()


var_Standaufsicht = 0
var_BeginnZeit = datetime.datetime.now()




def Schuetzeanlegen(User, StandID, Platz, KaliberID, Beginn, Standaufsicht): 
    print
    try: 
        mydb = MySQLdb.connect(host="10.100.124.14", user="XXX", passwd="XXX", db="Schiessbuch", port=3307)
 
        mycursor = mydb.cursor() 
 
        sql1 = """INSERT INTO `tbl_Schiesstand` (`UserID`, `StandID`, `Platz`, `KaliberID`, `Beginn`, `Standaufsicht`) VALUES (%s, %s, %s, %s, %s, %s)"""
        sqlInsertData = (User, StandID, Platz, KaliberID, Beginn, Standaufsicht) 
 
        
        mycursor.execute(sql1, sqlInsertData) 
        mydb.commit() 
       
        print
        print ("Du wurdest erfolgreich registriert") 
 
    except MySQLdb.Error as error : 
        mydb.rollback() 
        print("Failed to insert into MySQL table {}".format(error)) 
 
    finally: 
        #closing database connection. 
        if(mydb.ping()): 
            mycursor.close() 
            mydb.close() 
            print("MySQL connection is closed") 



Schuetzeanlegen(var_User, var_StandID, var_Platz, var_KaliberID, var_BeginnZeit, var_Standaufsicht)

Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Bei Python3 haben einfache `print`-Referenzierungen keine Wirkung, Du mußt `print` aufrufen.

Halte Dich an die Namenskonvention: Funktionen, wie Variablennamen schreibt man klein_mit_unterstrich.
Die `my`-Präfixe bei Deinen ganzen Variablen sind überflüssig (oder gibt es auch yourdb?).
Vermeide auch Abkürzungen bei Tabellen. Was soll bei UName und UVorname das U?
Wenn Du mit `with` arbeitest, sollte im Fehlerfall das `rollback` automatisch ablaufen, das muß man nicht explizit aufrufen. Die Fehlerausgabe ist auch Falsch, weil Du im try-Block gar kein `INSERT` ausführst. Wenn Du eine Exception nicht sinnvoll abarbeiten kannst, dann als es ganz sein.
`if` ist keine Funktion, die Klammern also überflüssig.
Im Fehlerfall ist im zweifel `mydb` nicht definiert, ein `mydb.ping` führt also zu einen NameError.

Niemals nackte `except` benutzen, sondern nur konkrete Fehlermeldungen abfangen. Bei "User ID eingeben" kann die Umwandlung in int fehlschlagen, das gibt einen ValueError. Wenn keine Zahl eingegeben wurde, besser nochmal nachfragen. `sys.exit` hat in einem sauberen Programm nichts verloren. Von daher sollte aller ausführbarer Code nicht auf oberster Ebene stehen, sondern in eine Funktion wandern, die normalerweise `main` genannt wird. Die kann man dann einfach durch `return` verlassen. Damit ergibt sich auch automatisch die nächste Forderunge: niemals ausführbaren Code und Funktionsdefinitionen mischen.

Es ist schlecht, dass jede Funktion wieder die Datenbank öffnet, so hast Du an vielen Stellen gleichen Code und mußt sogar bei Änderungen des Passworts das an vielen Stellen wiederholen. Besser eine Funktion schreiben, die die Datenbank öffnet (Username/Passwort etc. als Konstanten am Anfang der Datei (oder in einer Konfigurationsdatei)) speichern). Die Datenbankinstanz dann an die Funktionen als Parameter übergeben. Die bleibt während des gesamten Programmablaufs geöffnet.

Stand-ID-Abfrage ist wieder fast der selbe Code wie User-ID, das ist also besser eine Funktion, die mit unterschiedlichen Parametern aufgerufen wird.
In `Schuetzeanlegen` benutzt Du dann kein `with mydb:`. Warum?

Das var-Präfix ist wie das my-Präfix Unsinn.
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Guten Morgen,

ich muss deine Hilfe erstmal langsam verstehen.
ich habe mal aus mydb db gemacht und mycursor Cursor
dann habe ich alles aufrufbare in eine def main(): gepackt
Das try and expec habe ich bei den Select Anweisungen gelöscht.

Was ich gerade überlege ist, wie ich gescheit den connect der db in eine Funktion verwurste

UName und UVorname sind User Name und User Vorname
Das habe ich so gemacht, weil oft in der SQL Welt Name als Referenz zum einem Objekt steht.



So sieht der COde gerade aus:

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: iso-8859-1 -*-
# -*- encoding: iso-8859-15 -*-
# SchuetzeAnlegen.py 


import sys
import RPi.GPIO as GPIO
import MFRC522
import signal
import MySQLdb
import datetime

def main():
    var_Standaufsicht = 0
    var_BeginnZeit = datetime.datetime.now()

    print("Schiessbuch")
    print
    print("Bitte erfasse deine Daten!")
    print
    
    BenutzerAnzeigen()
    try:
        print
        var_User = int(input("Bitte deine User ID eingeben: "))
    except:
        print("Fehler: Keine Zahl eingegeben.")
    
   
    StandAnzeigen()
    try:
        print
        var_StandID = int(input("Bitte Stand eingeben: "))
    except:
        print("Fehler: Keine Zahl eingegeben.")
        
    KaliberAnzeigen()

    try:
        print
        var_KaliberID = int(input("Bitte Kaliber eingeben: "))
    except:
        print("Fehler: Keine Zahl eingegeben.")
        
        #Anfrage Platz
    print
    try:
        var_Platz = int(input("Auf welchem Stand schiesst du?: "))
    except:
        print("Fehler: Keine Zahl eingegeben.")
        
    Schuetzeanlegen(var_User, var_StandID, var_Platz, var_KaliberID, var_BeginnZeit, var_Standaufsicht)
   

    
    
def dbconnect():
    db = MySQLdb.connect(host="10.100.124.14", user="XXX", passwd="XXX", db="Schiessbuch", port=3307)
    cursor = db.cursor(MySQLdb.cursors.DictCursor)
    return db, cursor





def BenutzerAnzeigen():
    print
     
    db = MySQLdb.connect(host="10.100.124.14", user="XXX", passwd="XXX", db="Schiessbuch", port=3307)
 
    cursor = db.cursor(MySQLdb.cursors.DictCursor)
 
        
    with db:
        cursor.execute("Select tbl_Benutzer.ID, tbl_Benutzer.UName, tbl_Benutzer.UVorname FROM tbl_Benutzer INNER JOIN tbl_Karten ON tbl_Benutzer.ID = tbl_Karten.UserID") 
        rows = cursor.fetchall()

    for row in rows:
           print row["ID"], row["UName"], row["UVorname"]
            
 

def StandAnzeigen():
    print
    
    db = MySQLdb.connect(host="10.100.124.14", user="XXX", passwd="XXX", db="Schiessbuch", port=3307)
 
    cursor = db.cursor(MySQLdb.cursors.DictCursor)
 
        
    with db:
        cursor.execute("Select ID, StandLang From tbl_Stand") 
        rows = cursor.fetchall()

    for row in rows:
            print row["ID"], row["StandLang"]
            
  


def KaliberAnzeigen():
    print
     
    db = MySQLdb.connect(host="10.100.124.14", user="XXX", passwd="XXX", db="Schiessbuch", port=3307)
 
    cursor = db.cursor(MySQLdb.cursors.DictCursor)
 
        
    with db:
        cursor.execute("Select ID, KaliberLang From tbl_Kaliber") 
        rows = cursor.fetchall()

    for row in rows:
            print row["ID"], row["KaliberLang"]
           
 
 


def Schuetzeanlegen(User, StandID, Platz, KaliberID, Beginn, Standaufsicht): 
    print
    try: 
        db = MySQLdb.connect(host="10.100.124.14", user="XXX", passwd="XXX", db="Schiessbuch", port=3307)
 
        cursor = db.cursor() 
 
        sql1 = """INSERT INTO `tbl_Schiesstand` (`UserID`, `StandID`, `Platz`, `KaliberID`, `Beginn`, `Standaufsicht`) VALUES (%s, %s, %s, %s, %s, %s)"""
        sqlInsertData = (User, StandID, Platz, KaliberID, Beginn, Standaufsicht) 
 
        
        cursor.execute(sql1, sqlInsertData) 
        db.commit() 
       
        print
        print ("Du wurdest erfolgreich registriert") 
 
    except MySQLdb.Error as error : 
        db.rollback() 
        print("Failed to insert into MySQL table {}".format(error)) 
 
    finally: 
        #closing database connection. 
        if(db.ping()): 
            cursor.close() 
            db.close() 
            print("MySQL connection is closed") 



main()

matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Der Code wird übersichtlicher *freu :-)

Habe ein def connect(): eingebaut mit return

Dazu habe ich ein WHERE Statement eingebaut, um nach der Standselektion nur noch die korrekten Kaliber zubekommen.
Dazu habe ich in der Datenbank eine weitere Abhängigkeit zu den Tabellen Kaliber und Stand eingebaut.

Code: Alles auswählen

#!/usr/bin/python3
# -*- coding: iso-8859-1 -*-
# -*- encoding: iso-8859-15 -*-
# SchuetzeAnlegen.py 


import sys
import RPi.GPIO as GPIO
import MFRC522
import signal
import MySQLdb
import datetime

def main():
    var_Standaufsicht = 0
    var_BeginnZeit = datetime.datetime.now()

    print("Schiessbuch")
    print
    print("Bitte erfasse deine Daten!")
    print
    
    BenutzerAnzeigen()
    try:
        print
        var_User = int(input("Bitte deine User ID eingeben: "))
    except:
        print("Fehler: Keine Zahl eingegeben.")
    
   
    StandAnzeigen()
    try:
        print
        var_StandID = int(input("Bitte Stand eingeben: "))
    except:
        print("Fehler: Keine Zahl eingegeben.")
        
    KaliberAnzeigen(var_StandID)

    try:
        print
        var_KaliberID = int(input("Bitte Kaliber eingeben: "))
    except:
        print("Fehler: Keine Zahl eingegeben.")
        
        #Anfrage Platz
    print
    try:
        var_Platz = int(input("Auf welchem Stand schiesst du?: "))
    except:
        print("Fehler: Keine Zahl eingegeben.")
        
    Schuetzeanlegen(var_User, var_StandID, var_Platz, var_KaliberID, var_BeginnZeit, var_Standaufsicht)
   

    
    
def connect():
    db = MySQLdb.connect(host="10.100.124.14", user="XXX", passwd="XXX", db="Schiessbuch", port=3307)
    cursor = db.cursor(MySQLdb.cursors.DictCursor)
    return cursor, db





def BenutzerAnzeigen():
    print
     
    cursor, db = connect()
        
    with db:
        cursor.execute("Select tbl_Benutzer.ID, tbl_Benutzer.UName, tbl_Benutzer.UVorname FROM tbl_Benutzer INNER JOIN tbl_Karten ON tbl_Benutzer.ID = tbl_Karten.UserID") 
        rows = cursor.fetchall()

    for row in rows:
           print row["ID"], row["UName"], row["UVorname"]
            
 

def StandAnzeigen():
    print
    
    db = MySQLdb.connect(host="10.100.124.14", user="Web_Schiessbuch", passwd="Pw$Schiessbuch", db="Schiessbuch", port=3307)
 
    cursor = db.cursor(MySQLdb.cursors.DictCursor)
 
        
    with db:
        cursor.execute("Select ID, StandLang From tbl_Stand") 
        rows = cursor.fetchall()

    for row in rows:
            print row["ID"], row["StandLang"]
            



def KaliberAnzeigen(standID):
    print
     
    cursor, db = connect()
 
        
    with db:
        cursor.execute("Select tbl_Kaliber.ID, tbl_Kaliber.KaliberLang, tbl_Stand.Standlang From tbl_Stand INNER JOIN tbl_Kaliber ON tbl_Stand.ID = tbl_Kaliber.StandID Where tbl_Stand.ID = %s", (standID,)) 
        rows = cursor.fetchall()

    for row in rows:
            print row["ID"], row["KaliberLang"]
           
 
 


def Schuetzeanlegen(User, StandID, Platz, KaliberID, Beginn, Standaufsicht): 
    print
    try: 
        cursor, db = connect()
 
        sql1 = """INSERT INTO `tbl_Schiesstand` (`UserID`, `StandID`, `Platz`, `KaliberID`, `Beginn`, `Standaufsicht`) VALUES (%s, %s, %s, %s, %s, %s)"""
        sqlInsertData = (User, StandID, Platz, KaliberID, Beginn, Standaufsicht) 
 
        
        cursor.execute(sql1, sqlInsertData) 
        db.commit() 
       
        print
        print ("Du wurdest erfolgreich registriert") 
 
    except MySQLdb.Error as error : 
        db.rollback() 
        print("Failed to insert into MySQL table {}".format(error)) 
 
    finally: 
        #closing database connection. 
        if(db.ping()): 
            cursor.close() 
            db.close() 
            print("MySQL connection is closed") 


connect()
main()

Benutzeravatar
__blackjack__
User
Beiträge: 13069
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@matze1708: Die Begründung für das U verstehe ich nicht. Das es sich um einen Benutzernamen handelt, wird ja schon dadurch klar, dass der Name in der Benutzer-Tabelle ist. Das ist genau wie bei anderen Programmiersprachen mit Verbunddatentypen wo man den Namen des Datentyps ja auch nicht vor alle Felder/Attribute stellt. Auch bei SQL haben kryptische Abkürzungen das Problem, dass sie, nun ja, kryptisch sind, also müsste die Spalte ja eigentlich `benutzer_vorname` heissen. Und kann dann über `benutzer.benutzer_vorname` angesprochen werden. Was aber so gar keinen Vorteil gegebenüber `benutzer.vorname` hat. 'U' ist übrigens auch deswegen blöd weil die Tabelle bei Dir ja Deutsch benannt ist und eine englischer mit einem Buchstaben abgekürzter Präfix alles andere als naheliegend ist.

Und wenn ein Name in SQL ein Fremdschlüssel ist, also das was bei OOP eine Referenz zu einem anderen Objekt ist, dann hängt man da üblicherweise einen `_id`-Suffix an den Namen um Referenzen von direkten Werten unterscheiden zu können. Wenn man ein ORM verwendet, kann man den Namen ohne diesen Suffix dann tatsächlich für eine Referenz zu dem entsprechenden Objekt verwenden.

Bei SQL verwende ich nur Kleinbuchstaben für Namen und ansonsten die gleichen Namenskonventionen wie für Python, das macht die Abbildung auf Objekte mit einem ORM einfacher. Nur Kleinbuchstaben weil SQL die Gross-/Kleinschreibung bei Namen ja egal ist. In Fehlermeldungen werden einem Namen dann im Zweifelsfall komplett klein oder komplett gross geschrieben angezeigt, und da sind Unterstriche zwischen den einzelnen Worten aus denen ein Name zusammengesetzt ist, leichter zu lesen, als wenn das alles ohne visuelle Trennung hintereinander geklatscht wird.

Wie ist der Quelltext denn nun tatsächlich kodiert? Und was spricht gegen UTF-8? Nicht nur dass man die Kodierung für den Quelltext dann nicht angeben muss, man kann auch alle Unicode-Zeichen im Quelltext verwenden.

Der Quelltext ist kein Python 3, das heisst wenn Du den ausgeführt hast, dann mit Python 2. Die erste Zeile wäre dann also falsch, beziehungsweise sollte Du *wirklich* Python 3 verwenden. Python 2 ist am Ende.

Vier von den sechs Importen werden überhaupt nicht verwendet.

Der `connect()`-Aufruf auf Modulebene macht keinen Sinn, weil da ja auch gar nichts mit den Rückgabewerten gemacht wird.

Das ist auch so noch nicht sinnvoll gelöst, weil die DB-Verbindung etwas ist was langlebiger sein sollte. Die erstellt man in der Regel einmal und reicht sie dann als Argument herum.

In einer Funktion machst Du dann doch noch mal eine Verbindung nicht über die `connect()`-Funktion auf.

Geh mal bitte durch den Quelltext um passe alle Namen an die Python-Konventionen an. Siehe auch den Style Guide for Python Code.

Das ``with db:`` funktioniert ist ein Implementierungsdetail von `MySQLdb`. Das wird nicht von der DB API v2 garantiert und muss bei anderen Modulen für MySQL oder auch anderen DBMS nicht funktionieren. Da fehlt also ein `contextlib.closing()` damit man ``with`` verwenden kann.

`Cursor`-Objekte muss man auch schliessen. Nicht jedes DB-Modul/DBMS fordert das tatsächlich, aber die DB API v2 sagt, dass das gefordert werden kann.

Für den Zugriff auch ”Datensatz-Wörterbücher” finde ich das externe `addict`-Modul mit seinem `Dict`-Datentyp sehr praktisch. Wobei da dann auch die Bennung der Datenbankspalten nach Python-Namenskonventionen Sinn macht.

Das die Datenbankabfragen mit Anzeigen für den Benutzer vermischt sind ist nicht gut. Die Programmlogik sollte von der Benutzerinteraktion getrennt sein. Man möchte die Programmlogik ja nicht noch einmal programmieren, nur weil man die Daten dann in einer GUI ausgibt, statt per `print()` in einer Textkonsole.

Ich muss dann auch einfach noch mal SQLAlchemy erwähnen. Selbst wenn man das ORM nicht verwendet, macht es einem die Arbeit mit SQL-Datenbanken einfacher. Ich sehe aber auch keinen Grund das ORM hier nicht zu verwenden. Objekte denen man auch Methoden verpassen kann und das man die SQL-Abfragen nicht mehr selbst schreiben muss machen das ganze leichter.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Hast Du jetzt das richtige Passwort hier gepostet? `Pw$Schiessbuch` solltest Du aber sowieso ändern, das ist zu einfach.
Wie schon geschrieben, solltest Du nicht jedes mal eine neue Verbindung zur Datenbank aufbauen, sondern einmal am Anfang. Ein Cursor dagegen ist etwas kurzlebiges und sollte dann erzeugt werden, wenn man konkret eine Abfrage macht, das geht am einfachsten mit `with`.
Die Namen halten sich immer noch nicht an die Konvention und auch bei Datenbanktabellen sollte man auf sprechende Namen setzen. Dazu gehört dass das überflüssige tbl_-Präfix wegkommt.

Codierung sollte unter Python3 eigentlich immer UTF8 (das ist der Default) sein.

Code: Alles auswählen

#!/usr/bin/python3
import sys
import RPi.GPIO as gpio
import MFRC522
import MySQLdb

DB_HOST = "10.100.124.14"
DB_USER = "XXX"
DB_PASSWORD = "XXX"

def connect():
    return MySQLdb.connect(host=DB_HOST, port=3307,
        user=DB_USER , passwd=DB_PASSWORD, db="Schiessbuch",
        cursorclass=MySQLdb.cursors.DictCursor)

def benutzer_anzeigen(db):
    print()
    with db as cursor:
        cursor.execute("""Select tbl_Benutzer.ID, tbl_Benutzer.UName, tbl_Benutzer.UVorname
            FROM tbl_Benutzer INNER JOIN tbl_Karten ON tbl_Benutzer.ID = tbl_Karten.UserID""")
        for row in cursor:
           print row["ID"], row["UName"], row["UVorname"]

def stand_anzeigen(db):
    print()
    with db as cursor:
        cursor.execute("Select ID, StandLang From tbl_Stand") 
        for row in cursor:
            print row["ID"], row["StandLang"]

def kaliber_anzeigen(stand_id):
    print()
    with db as cursor:
        cursor.execute("""Select tbl_Kaliber.ID, tbl_Kaliber.KaliberLang, tbl_Stand.Standlang
            From tbl_Stand INNER JOIN tbl_Kaliber ON tbl_Stand.ID = tbl_Kaliber.StandID
            Where tbl_Stand.ID = %s""", (stand_id,))
        for row in cursor:
            print row["ID"], row["KaliberLang"]

def schuetze_anlegen(user_id, stand_id, platz, kaliber_id, standaufsicht):
    print()
    with db as cursor:
        sql_query = """INSERT INTO `tbl_Schiesstand` (`UserID`, `StandID`, `Platz`, `KaliberID`, `Beginn`, `Standaufsicht`) VALUES (%s, %s, %s, %s, NOW(), %s)"""
        data = (user_id, stand_id, platz, kaliber_id, standaufsicht) 
        cursor.execute(sql_query, data) 
    print()
    print("Du wurdest erfolgreich registriert") 

def input_int(prompt):
    while True:
        try:
            print()
            return int(input(prompt))
        except ValueError:
            print("Fehler: Keine Zahl eingegeben.")
            
def main():
    print("Schiessbuch")
    print()
    print("Bitte erfasse deine Daten!")
    print()
    db = connect()

    benutzer_anzeigen(db)
    user_id = input_int("Bitte deine User ID eingeben: ")
    
    stand_anzeigen(db)
    stand_id = input_int("Bitte Stand eingeben: ")
    
    kaliber_anzeigen(stand_id)
    kaliber_id = input_int("Bitte Kaliber eingeben: ")
    
    platz = input_int("Auf welchem Stand schiesst du?: ")
    
    standaufsicht = 0
    schuetze_anlegen(user_id, stand_id, platz, kaliber_id, standaufsicht)

if __name__ == '__main__':
    main()
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Hallo,

Danke für deine ausführliche Hilfe.

Ich muss mich da mal Schritt für Schritt durch arbeiten.
Wie ist der Quelltext denn nun tatsächlich kodiert? Und was spricht gegen UTF-8? Nicht nur dass man die Kodierung für den Quelltext dann nicht angeben muss, man kann auch alle Unicode-Zeichen im Quelltext verwenden.
Ich habe das ISo im Kopf entfernt und folgendes eingetragen:

Code: Alles auswählen

# -*- coding: utf-8 -*-
Der Quelltext ist kein Python 3, das heisst wenn Du den ausgeführt hast, dann mit Python 2. Die erste Zeile wäre dann also falsch, beziehungsweise sollte Du *wirklich* Python 3 verwenden. Python 2 ist am Ende.
Wie bekomme ich das einheitlich auf Python 3?
Habe gesehen das bei einem Fehler irgendwas mit Python 2.7 angezeigt worden ist.
Der `connect()`-Aufruf auf Modulebene macht keinen Sinn, weil da ja auch gar nichts mit den Rückgabewerten gemacht wird.
Das ist auch so noch nicht sinnvoll gelöst, weil die DB-Verbindung etwas ist was langlebiger sein sollte. Die erstellt man in der Regel einmal und reicht sie dann als Argument herum.
In einer Funktion machst Du dann doch noch mal eine Verbindung nicht über die `connect()`-Funktion auf.
Hierbei wäre ich um Beispiel glücklich. Habe mich da in diversen Beiträgen belesen, und kann leider nur die Funktion def connect(): finden die man dann vor der main ausführt.
`Cursor`-Objekte muss man auch schliessen. Nicht jedes DB-Modul/DBMS fordert das tatsächlich, aber die DB API v2 sagt, dass das gefordert werden kann.
Das dachte ich getan zu haben in der letzten Funktion unter finaly
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Danke für dein Beispiel.

das sieht ja ganz anders aus :-)

Muss ich mir nach dem Mittag mal in Ruhe durchsehen und verstehen

Ich werde die Namen in der DB anpassen.

Ich habe mal mit Access und MSSQL angefangen. Da hat es sich einfacher gezeigt, Tabellen mit tbl_ und Abfragen qry_ oder Stored Procedur mit SP_ anzufangen. Daher habe ich das hier auch so getan.
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Ich habe mir mal den Teil

Code: Alles auswählen

def connect():
    return MySQLdb.connect(host=DB_HOST, port=3307,
        user=DB_USER , passwd=DB_PASSWORD, db="Schiessbuch",
        cursorclass=MySQLdb.cursors.DictCursor)
angesehen.

Dabei hat die Konsole einen Fehler festgestellt.
File "SchuetzeAnlegen.py", line 14, in connect
cursorclass=MySQLdb.cursors.DictCursor)
AttributeError: 'module' object has no attribute 'cursors'
BIn das gerade mal am Googln und verstehen.
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Hallo,

ich muss hier leider noch mal fragen.

Warum kommt hierbei die Meldung das der Cursor nicht im Modul ist?

Code: Alles auswählen

#!/usr/bin/python3
import sys
import RPi.GPIO as gpio
#import MFRC522
import MySQLdb

DB_HOST = 
DB_USER = 
DB_PASSWORD = "

def connect():
    return MySQLdb.connect(host=DB_HOST, port=3307,
        user=DB_USER , passwd=DB_PASSWORD, db="Schiessbuch",
        cursorclass=MySQLdb.cursors.DictCursor)
Traceback (most recent call last):
File "SchuetzeAnlegen-Forum.py", line 79, in <module>
main()
File "SchuetzeAnlegen-Forum.py", line 62, in main
db = connect()
File "SchuetzeAnlegen-Forum.py", line 14, in connect
cursorclass=MySQLdb.cursors.DictCursor)
AttributeError: module 'MySQLdb' has no attribute 'cursors'
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Ich hatte mal folgendes Probiert

Code: Alles auswählen

def connect():
    conn =  MySQLdb.connect(host=DB_HOST, port=3307,
        user=DB_USER , passwd=DB_PASSWORD, db="Schiessbuch")
      return conn.cursor(cursorclass=MySQLdb.cursors.DictCursor)


Das ging auch, bei der ersten Abfrage, bei der 2. sagte er der Cursor wäre closed
Sirius3
User
Beiträge: 17737
Registriert: Sonntag 21. Oktober 2012, 17:20

Du brauchst ein

Code: Alles auswählen

import MySQLdb.cursors
Das zweite Beispiel, das funktioniert, dürfte daher auch nicht funktionieren.
matze1708
User
Beiträge: 112
Registriert: Dienstag 12. März 2019, 11:49

Ok Danke. Das scheint damit zu klappen.

Bekomme aber weiterhin Meldungen...
Traceback (most recent call last):
File "SchuetzeAnlegen-Forum2.py", line 80, in <module>
main()
File "SchuetzeAnlegen-Forum2.py", line 65, in main
benutzer_anzeigen(db)
File "SchuetzeAnlegen-Forum2.py", line 19, in benutzer_anzeigen
with db as cursor:
AttributeError: __exit__
Antworten