Lär dig SQL

Back to All Courses

Lesson 11

Använda en databas i en applikation

by Ted Klein Bergman

Dags för backend!

SQL är som sagt ett programmeringsspråk som man kan använda för att kommunicera med en databas, men som inte kan skapa applikationer. Eftersom detta inte är en kurs i att utveckla applikationer så kommer vi använda oss av Tweeter. Se till att ni har kört filen Tweeter/setup.py, startat databasen (genom att starta psql) och kört Tweeter/data/create.sql ifrån psql (förklarat i kapitlet Modifiera tabeller). Efter ni startat programmet (Tweeter/app/tweeter.py) kan ni öppna webbrowsern och gå in på http://127.0.0.1:5000/. Om allt har gått som det ska möts ni av detta:

Nu är det dags för kod! All kod ska skrivas i filen Tweeter/app/database_exercise.py. I filen Tweeter/app/database.py finns förslagna lösningar.

Connection

Först måste vi koppla vårat program till våran databas. För att göra det behöver vi kalla på funktionen connect med dessa argument:

  1. dbname är namnet på databasen du försöker koppla till.

  2. user är användaren för databasen. En databas kan ha flera olika användare som har olika saker de får och inte får göra. Om ni inte har skapat någon användare så sätter ni detta argument till "postgres".

  3. password är lösenordet för användaren. Om ni inte har satt något lösenord så kan ni lämna detta argument tomt.

  4. host är IP-addressen för databasen. I vårat fall kommer vi använda oss av "localhost", vilket betyder "min egna IP-address".

  5. port är porten vi vill gå genom. Vi använder oss av standardvärdet.

connection = connect(
  dbname='tweeter', user='tweeter_admin', password='1234', host='localhost', port=5432
)

Testa att lägga in denna kod globalt i Tweeter/app/database_exercise.py. Testa sedan att köra programmet igen. Om connect-funktionen ger ett felmeddelande kan det vara för att ni inte har startat databasen (via psql) eller att argumenten inte stämmer. Skicka in argumenten som ges när ni startar psql i hakparenteser (förutom dbname och username som ska vara tweeter respektive tweeter_admin).

När vi har skapat en connection kan vi börja skicka queries till vår databas. För att göra det måste vi först skapa ett cursor-objekt.

Cursor

En cursor är ett objekt som kan interagera med tabeller. Den skapas från connection-objektet via metoden cursor().

cursor = connection.cursor(cursor_factory=NamedTupleCursor)

Vi gav cursorn argumentet cursor_factory=NamedTupleCursor för att de tuples vi får tillbaka från en query ska vara python objekt istället för listor, då det är snyggare att arbeta med. Projektet är byggt runt detta dessutom så det är nödvändigt.

Det är via cursorn vi nu kan skicka våra queries. Alla queries skickas som en sträng till metoden cursor.execute(query), och resultatet från queryn hämtas med metoden cursor.fetchall().

Vi kan testa att implementer en funktion direkt. Funktionen get_newest_tweets(number) är den funktion som returnerar de tweets som kommer att visas på startsidan. Just nu struntar vi i parametern number då vi kommer prata om hur man hanterar argument i queries i nästa kapitel.

def get_newest_tweets(number):
    """
    Fetch x amount of tweets ordered by time_posted (descending order).

    The values in each tuple should be:
        tweet_id, poster_id, username, content, time_posted

    Return:
         all tuples in a list.

    Example:

        all_tuples = []
        for tuple in get_tuples_from_query():
            all_tuples.append(tuple)

        return all_tuples

    Hardness:
        2
    """
    query = """
        SELECT tweet_id, poster_id, username, content, time_posted
        FROM   users JOIN tweets ON user_id = poster_id
        ORDER BY time_posted DESC;
        """
    cursor.execute(query)
    table  = cursor.fetchall()
    result = []
    for tweet in table:
        result.append(tweet)
    return result

Något att uppmärksamma på är att bägge av cursorns metoder kan ge ett felmeddelanden om vår query inte är korrekt, så för att hantera dessa fall korrekt ska de omges av ett try-except block.

try:
    cursor.execute(query)
except Error as error:
    print(error.pgerror)

try:
    table = cursor.fetchall()
except Error as error:
    print(error.pgerror)

Detta kan vara jobbigt att göra detta för alla queries, så det är rekommenderat att skapa en (eller flera) hjälpklasser eller hjälpfunktioner som gör det åt oss. Efter du har implementerat denna metod kan du köra Tweeter/app/tweeter.py igen. Om allt gick korrekt ska du nu se tweets på startsidan!