PostgrSQL

Installation und Anwendung von Datenbankschnittstellen wie SQLite, PostgreSQL, MySQL, der DB-API 2.0 und sonstigen Datenbanksystemen.
Antworten
Bavarian_programmer
User
Beiträge: 1
Registriert: Freitag 20. September 2019, 10:20
Wohnort: Bayern,Deutschland

Freitag 20. September 2019, 10:30

Hallo user,

ich hätte eine frage bezüglich dem einbinden einer PostgreSQL Tabelle in web2py.

Meine Tabelle:
{'result': [{'id': 1, 'name': 'Lovász', 'vorname': 'Gergö', 'geburtsdatum': datetime.date(1980, 11, 24), 'email': 'gergoe@deutschland.de'}, {'id': 2, 'name': 'Trouble', 'vorname': 'John', 'geburtsdatum': datetime.date(2000, 2, 1), 'email': 'john@trouble.de'}, {'id': 4, 'name': 'Diesl', 'vorname': 'Greta', 'geburtsdatum': datetime.date(2000, 1, 1), 'email': 'greta@diesl.de'}, {'id': 5, 'name': 'Bauer', 'vorname': 'Sepp', 'geburtsdatum': datetime.date(2000, 1, 1), 'email': 'sepp@bauer.de'}, {'id': 8, 'name': 'test', 'vorname': 'test', 'geburtsdatum': datetime.date(2000, 1, 1), 'email': 'TEST@gmail.com'}, {'id': 9, 'name': 'Dobl', 'vorname': 'Simon', 'geburtsdatum': datetime.date(2000, 2, 2), 'email': 'simon@dobl.de'}, {'id': 10, 'name': 'Tischl', 'vorname': 'Tom', 'geburtsdatum': datetime.date(2000, 1, 1), 'email': 'tom.test@test.de'}, {'id': 11, 'name': 'Frank', 'vorname': 'Fabian', 'geburtsdatum': datetime.date(2003, 8, 21), 'email': 'fabian-frank@gmail.com'}], 'error': None}

nun möchte ich geziehlt abfragen über phyton z.B. nach dem namen und vornamen des kunden mit der ID 2

dafür hätte ich schon versucht dass ich die Tabelle wie ein dictionary behandle und auch so meine Abfrage gestalte. Jedoch war ich damit nicht erfolgreich.

Vielen Dank im Vorraus für eure hilfe
Fabian
Benutzeravatar
sparrow
User
Beiträge: 1360
Registriert: Freitag 17. April 2009, 10:28

Freitag 20. September 2019, 12:20

Das ist keine Tabelle sonder ein dict in Python.

Benutzt du ein Framework um auf die Datenbank zuzugreifen?
Sirius3
User
Beiträge: 10595
Registriert: Sonntag 21. Oktober 2012, 17:20

Freitag 20. September 2019, 13:46

@Bavarian_programmer: wie bekommst Du diese Daten? Wenn Du eine Datenbank benutzt, dann verwendet man SQL-Abfragen um bestimmte Werte zu bekommen, hier also etwas in der Art "SELECT name, vorname FROM kunden WHERE ID=%s". Welches Framework benutzt Du für die Datenbank? Zeig den Code, den Du bereits hast, das macht das Erklären viel einfacher.
Benutzeravatar
__blackjack__
User
Beiträge: 4243
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Samstag 21. September 2019, 12:05

@Bavarian_programmer: für so umfangreiche verschachtelte Grunddatentypen bietet es sich an die mit `pprint()` aus dem `pprint()`-Modul auszugeben:

Code: Alles auswählen

In [5]: from pprint import pprint                                               

In [6]: pprint(d)                                                               
{'error': None,
 'result': [{'email': 'gergoe@deutschland.de',
             'geburtsdatum': datetime.date(1980, 11, 24),
             'id': 1,
             'name': 'Lovász',
             'vorname': 'Gergö'},
            {'email': 'john@trouble.de',
             'geburtsdatum': datetime.date(2000, 2, 1),
             'id': 2,
             'name': 'Trouble',
             'vorname': 'John'},
            {'email': 'greta@diesl.de',
             'geburtsdatum': datetime.date(2000, 1, 1),
             'id': 4,
             'name': 'Diesl',
             'vorname': 'Greta'},
            {'email': 'sepp@bauer.de',
             'geburtsdatum': datetime.date(2000, 1, 1),
             'id': 5,
             'name': 'Bauer',
             'vorname': 'Sepp'},
            {'email': 'TEST@gmail.com',
             'geburtsdatum': datetime.date(2000, 1, 1),
             'id': 8,
             'name': 'test',
             'vorname': 'test'},
            {'email': 'simon@dobl.de',
             'geburtsdatum': datetime.date(2000, 2, 2),
             'id': 9,
             'name': 'Dobl',
             'vorname': 'Simon'},
            {'email': 'tom.test@test.de',
             'geburtsdatum': datetime.date(2000, 1, 1),
             'id': 10,
             'name': 'Tischl',
             'vorname': 'Tom'},
            {'email': 'fabian-frank@gmail.com',
             'geburtsdatum': datetime.date(2003, 8, 21),
             'id': 11,
             'name': 'Frank',
             'vorname': 'Fabian'}]}
Das sieht doch gleich viel übersichtlicher aus.
Wenn Du die gewünschten Daten jetzt tatsächlich dort raus holen willst, musst Du halt Code schreiben der genau das macht. Also beispielsweise eine Schleife über die Liste die bei "result" hinterlegt ist wo Du prüfst ob das aktuelle Element beim Schlüssel "id" den Wert 2 hinterlegt hat.

Alternativ kommte man so etwas wie das `glom`-Modul verwenden:

Code: Alles auswählen

In [7]: import glom                                                             

In [8]: pprint(glom.glom(d, ("result", [glom.Check("id", equal_to=2, default=glom.SKIP)])))                                                             
[{'email': 'john@trouble.de',
  'geburtsdatum': datetime.date(2000, 2, 1),
  'id': 2,
  'name': 'Trouble',
  'vorname': 'John'}]
Aber nur wenn man tatsächlich nicht schon vorher bei der Datenbankabfrage entsprechend einschränken kann.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
jinroo
User
Beiträge: 9
Registriert: Dienstag 13. Oktober 2015, 16:30

Sonntag 29. September 2019, 14:00

Code: Alles auswählen

import psycopg2

connection = psycopg2.connect(
                                  user="database_user",
                                  password="MySuperSecretPass",
                                  host="127.0.0.1",
                                  port="5432",
                                  database="postgres_db_schema")
cursor = connection.cursor()
MyID = str(2) #woher auch immer diese ID kommt
postgreSQL_select_Query = "select id, name, vorname from kunden where ID = " + MyID + ";"

cursor.execute(postgreSQL_select_Query)
kunden_records = cursor.fetchall() 
   
for row in kunden_records:
       print("Id = ", row[0], )
       print("Name = ", row[1])
       print("Vorname  = ", row[2], "\n")
       
connection.close()


So könnte das aussehen, abhängig von deiner Umgebung und installierten Packeten
Sirius3
User
Beiträge: 10595
Registriert: Sonntag 21. Oktober 2012, 17:20

Sonntag 29. September 2019, 14:23

@jinroo: niemals Parameter in SQL-Statements hineinformatieren, dafür gibt es Platzhalter.
Man stückelt auch keine Strings mit + zusammen, und verwendet explizit str dafür.
Konvention ist, Variablennamen klein_mit_unterstrich zu schreiben.
Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht 7.
Benutzeravatar
__blackjack__
User
Beiträge: 4243
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Sonntag 29. September 2019, 14:33

@jinroo: So sollte das bitte *nicht* aussehen! Man formatiert keine Werte in SQL-Anweisungen in Zeichenketten. Insbesondere wenn die „woher auch immer“ kommen, hat man ein prima Sicherheitslücke gerissen. Aber auch wenn man die Werte besser unter Kontrolle hat, kann das ineffizient sein, weil der Datenbankadapter dann die SQL-Anweisung und ihre Verarbeitung zu einem Ablaufplan nicht cachen kann, wenn sich die Zeichenkette für jeden Wert ändert. In dies SQL-Anweisung gehören Platzhalter und die eigentlichen Werte werden als zweites Argument von `execute()` übergeben.

Namen werden in Python klein_mit_unterstrichen geschrieben. Ausnahmen sind Konstanten (KOMPLETT_GROSS) und Klassen (MixedCase). So etwas wie `postgreSQL_select_Query` geht gar nicht. Da werden ja sämtliche Varianten per Zufall gestreut eingesetzt.

Statt auf die Elemente von `row` per Index zuzugreifen, wäre es lesbarer die gleich in der Schleife an sinnvolle Namen zu binden.

Ungetestet:

Code: Alles auswählen

#!/usr/bin/env python3
from contextlib import closing

import psycopg2


def main():
    connection = psycopg2.connect(
        user="database_user",
        password="MySuperSecretPass",
        host="127.0.0.1",
        port="5432",
        database="postgres_db_schema",
    )
    with closing(connection):
        with closing(connection.cursor()):
            id_ = 2  # Woher auch immer diese ID kommt.
            cursor.execute(
                "SELECT id, name, vorname FROM kunde WHERE id=%s", [id_]
            )
            for id_, name, vorname in cursor.fetchall():
                print("Id =", id)
                print("Name =", name)
                print("Vorname =", vorname, "\n")


if __name__ == "__main__":
    main()
So ganz unabhängig ist das nicht von den Paketen weil die Platzhalter nicht für jedes DB-API V2-Modul gleich sein müssen. Das ist für mich auch schon ein Grund auf SQLAlchemy zu setzen, auch wenn man das ORM davon nicht nutzt.
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
Benutzeravatar
__blackjack__
User
Beiträge: 4243
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Sonntag 29. September 2019, 15:43

Das ganze mit SQLAlchemy und „reflection“ der vorhandenen Tabellen:

Code: Alles auswählen

#!/usr/bin/env python3
from sqlalchemy import create_engine, MetaData, select

DB_URL = (
    "postgresql+psycopg2://database_user:MySuperSecretPass@127.0.0.1:5432/"
    "postgres_db_schema"
)


def main():
    engine = create_engine(DB_URL)
    metadata = MetaData(engine, reflect=True)
    customer_table = metadata.tables["kunde"]
    query = select(
        [customer_table.c.id, customer_table.c.name, customer_table.c.vorname],
        customer_table.c.id == 2,
    )
    for row in engine.execute(query):
        print("ID =", row.id)
        print("Name =", row.name)
        print("Vorname =", row.vorname, "\n")


if __name__ == "__main__":
    main()
Falls man die Spalten nicht einschränken möchte sondern einfach alle bekommen möchte, kann man `select()` auch als Methode auf dem Tabellenobjekt aufrufen:

Code: Alles auswählen

def main():
    engine = create_engine(DB_URL)
    metadata = MetaData(engine, reflect=True)
    customer_table = metadata.tables["kunde"]
    for row in engine.execute(customer_table.select(customer_table.c.id == 2)):
        print("ID =", row.id)
        print("Name =", row.name)
        print("Vorname =", row.vorname, "\n")
Oder mit dem ORM, wo man Klassen für die Datensätze definiert denen man dann noch zusätzliches Verhalten mitgeben kann:

Code: Alles auswählen

#!/usr/bin/env python3
from sqlalchemy import Column, create_engine, INTEGER, TEXT
from sqlalchemy.orm import Session
from sqlalchemy.ext.declarative import declarative_base

DB_URL = (
    "postgresql+psycopg2://database_user:MySuperSecretPass@127.0.0.1:5432/"
    "postgres_db_schema"
)

Base = declarative_base()


class Customer(Base):
    __tablename__ = "kunde"

    id = Column(INTEGER, primary_key=True)
    surname = Column("name", TEXT, nullable=False)
    name = Column("vorname", TEXT, nullable=False)
    
    def __str__(self):
        return f"{self.full_name} (id={self.id})"
    
    @property
    def full_name(self):
        return f"{self.name} {self.surname}"
    


def main():
    engine = create_engine(DB_URL)
    session = Session(engine)
    for customer in session.query(Customer).filter_by(id=2):
        print(customer)
        print("ID =", customer.id)
        print("Name =", customer.surname)
        print("Vorname =", customer.name)
        print("Voller Name =", customer.full_name, "\n")


if __name__ == "__main__":
    main()
Ausgabe:

Code: Alles auswählen

Eric Idle (id=2)
ID = 2
Name = Idle
Vorname = Eric
Voller Name = Eric Idle
“Give a man a fire and he's warm for a day, but set fire to him and he's warm for the rest of his life.”
— Terry Pratchett, Jingo
Antworten