Kihagyás

Python - Flesk - SQLite

Az előzőekben megnéztük, hogy hogyan lehet egy egyszerű REST API-t készíteni Python segítségével. Most megnézzük, hogy hogyan lehet egy SQLite adatbázist használni a Flask alkalmazásunkban. Készítsünk egy egyszerű adatbázist, amelyben felhasználók adatait tároljuk. Az adatbázisban egy users tábla lesz, amelyben az alábbi mezők lesznek:

  • email - a felhasználó e-mail címe
  • password - a felhasználó jelszava

Az adatbázisunkat egy src/users.sqlite nevű fájlban fogjuk tárolni.

Adatbázis létrehozása

Hozz létre egy adatbázist, majd add ki az alábbi SQL parancsot, amely létrehozza az adatbázis táblát valamint a példa adatokat.

Segédprogram

Ajánlott egy segédprogramot használni az adatbázis létrehozásához és a példa adatok beillesztéséhez. Például a DB Browser for SQLite egy egyszerű, könnyen használható eszköz, amely segítségével könnyen létrehozhatod az adatbázist és a táblákat, valamint beillesztheted a példa adatokat.

1
2
3
4
5
6
7
CREATE TABLE users (
    email TEXT,
    password TEXT
);

INSERT INTO users (email, password) VALUES('johndoe@mail.com', 'jd123');
INSERT INTO users (email, password) VALUES('janedoe@mail.com', '123jd');

Adatbázis állomány

Ha elakadtál az adatbázis létrehozásában, ide kattintva letöltheted az általam készített users.sqlite adatbázis állományt.

Kiinduló program

from flask import Flask, jsonify, request
import sqlite3

app = Flask(__name__)
db = "users.sqlite"

"""
Ide jönnek a különböző végpontok

@app.route("/vegpont")
def get_users():
    pass
"""

if __name__ == "__main__":
    app.run(debug=True)

Végpont felhasználó adatának kikéréséhez

Összes felhasználó adatainak lekérése

Most, hogy létrehoztuk az adatbázist, készítsünk egy végpontot, amely visszaadja az összes felhasználó összes adatát.

@app.route("/users") #(1)
def get_users(): #(2)
    connection = sqlite3.connect(db) #(3)
    cursor = connection.cursor() #(4)
    cursor.execute("SELECT * FROM users") #(5)
    rekordok = cursor.fetchall() #(6)
    connection.close() #(7)

    users = list() #(8)
    for rekord in rekordok: #(9)
        item = {
            "email": rekord[0], #(10)
            "password": rekord[1] #(11)
        }
        users.append(item) #(12)

    return jsonify(users) #(13)
  1. URL útvonal deklarálása: Ez a sor regisztrál egy útvonalat a Flask alkalmazásban, ami azt jelenti, hogy amikor a /users útvonalra egy kérés érkezik, a Flask ezt a funkciót hívja meg.
  2. Funkció definíció: Definiál egy get_users nevű függvényt, ami nem fogad paramétert.
  3. Adatbázis-kapcsolat létrehozása: Létrehoz egy kapcsolatot az SQLite adatbázissal. A db változó nevű adatbázisfájlhoz kapcsolódik, amelynek helyét és nevét előzetesen definiálni kell.
  4. Cursor létrehozása: A kapcsolaton keresztül létrehoz egy kurzort, amely lehetővé teszi SQL utasítások végrehajtását az adatbázison.
  5. SQL lekérdezés: Lekérdezi az összes felhasználó adatait a users táblából.
  6. Adatok kinyerése: Az előző lépés során lekérdezett összes adatot kinyeri.
  7. Adatbázis-kapcsolat lezárása: Miután az adatokat kinyerte, lezárja az adatbázis-kapcsolatot.
  8. Üres lista létrehozása: Egy üres listát hoz létre a felhasználói adatok tárolására.
  9. Végigiterálás a rekordokon: Végigmegy az összes kinyert rekordon.
  10. E-mail cím kinyerése: Minden rekord első eleme lesz az e-mail cím.
  11. Jelszó kinyerése: Minden rekord második eleme lesz a jelszó.
  12. Felhasználó hozzáadása a listához: Minden kinyert adatpár (e-mail, jelszó) hozzáadása a listához egy szótár formájában.
  13. Adatok JSON formátumban való visszaadása: A felhasználói adatokat tartalmazó lista JSON formátumba konvertálása és visszaadása a kliensnek.

Egy felhasználó adatainak lekérése

Az alábbi kód egy adott e-mail cím alapján visszaadja a felhasználó adatait.

@app.route("/users/<email>") #(1)
def get_user(email): #(2)
    connection = sqlite3.connect(db) #(3)
    cursor = connection.cursor() #(4)
    cursor.execute("SELECT * FROM users WHERE email = ?", [email]) #(5)
    rekord = cursor.fetchone() #(6)
    connection.close() #(7)

    if rekord: #(8)
        item = {
            "email": rekord[0], #(9)
            "password": rekord[1] #(10)
        }
        return jsonify(item) #(11)
    else:
        return jsonify({"error": "Nincs ilyen felhasználó!"}), 404 #(12)
  1. Útvonal deklarálása: Meghatározza a /users/<email> végpontot, amely a GET kérésekre reagál, egy adott email című felhasználó adataival.
  2. Függvény definíciója: Definiál egy get_user nevű függvényt, ami egy email cím paramétert fogad.
  3. Adatbázis-kapcsolat létrehozása: Kapcsolódik az users.sqlite adatbázishoz.
  4. Kurzor létrehozása: Egy kurzort hoz létre, ami lehetővé teszi az adatbázisban való lekérdezések végrehajtását.
  5. Felhasználó adatainak lekérése: Lekérdezi az adott email című felhasználó adatait az adatbázisból.
  6. Első sor lekérése: A lekérdezés eredményéből az első sort kinyeri.
  7. Adatbázis-kapcsolat bezárása: Bezárja az adatbázis-kapcsolatot a lekérdezés után.
  8. Sor ellenőrzése: Ellenőrzi, hogy van-e találat az adott email címre.
  9. Email cím hozzáadása: Ha van találat, az email címet hozzáadja az item dict-hez.
  10. Jelszó hozzáadása: Hozzáadja a jelszót az item dict-hez.
  11. Adatok visszaadása: JSON formátumban visszaadja a felhasználó adatait.
  12. Hibaüzenet küldése: Ha nincs találat, egy hibaüzenetet küld vissza, jelezve, hogy nincs ilyen felhasználó, a válasz státusz kódja 404.

Összehasonlítás

@app.route("/users")
def get_users():
    connection = sqlite3.connect(db)
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM users")
    rekordok = cursor.fetchall()
    connection.close()

    users = list()
    for rekord in rekordok:
        item = {
            "email": rekord[0],
            "password": rekord[1]
        }
        users.append(item)

    return jsonify(users)
@app.route("/users/<email>")
def get_user(email):
    connection = sqlite3.connect(db)
    cursor = connection.cursor()
    cursor.execute("SELECT * FROM users WHERE email = ?", [email])
    rekord = cursor.fetchone()
    connection.close()

    if rekord:
        item = {
            "email": rekord[0],
            "password": rekord[1]
        }
        return jsonify(item)
    else:
        return jsonify({"error": "Nincs ilyen felhasználó!"}), 404

Végpont adatbeszúrásra

Emlékeztető

Az adatbázisba való adatbeszúrásra a POST metódust használjuk.

@app.route('/users', methods=['POST']) #(1)
def create_user(): #(2)
    data = request.json #(3)
    email = data['email'] #(4)
    password = data['password'] #(5)

    connection =  sqlite3.connect(db) #(6)
    cursor = connection.cursor() #(7)
    cursor.execute("INSERT INTO users (email, password) VALUES (?, ?)", [email, password]) #(8)
    connection.commit() #(9)
    connection.close() #(10)

    return jsonify({'success': True, 'email': email}), 201 #(11)
  1. Útvonal deklarálása: Meghatározza a /users végpontot POST metódussal, amely lehetővé teszi új felhasználó létrehozását.
  2. Függvény definíciója: Definiál egy create_user nevű függvényt.
  3. Kérés adatának kinyerése: Kinyeri a kérés JSON formátumú adatait.
  4. Felhasználónév kinyerése: Kinyeri a felhasználónév adatot a JSON-ből.
  5. Jelszó kinyerése: Kinyeri a jelszó adatot a JSON-ből.
  6. Adatbázis-kapcsolat létrehozása: Kapcsolódik az users.sqlite adatbázishoz.
  7. Kurzor létrehozása: Egy kurzort hoz létre az adatbázisműveletek végrehajtásához.
  8. Új felhasználó beszúrása: Beszúr egy új felhasználót az adatbázisba a megadott email és jelszó alapján.
  9. Változások véglegesítése: Véglegesíti a beszúrás műveletet az adatbázisban.
  10. Adatbázis-kapcsolat bezárása: Bezárja az adatbázis-kapcsolatot.
  11. Sikeres válasz küldése: Visszaküld egy JSON választ, amely megerősíti a sikeres felhasználó létrehozást, valamint tartalmazza a létrehozott felhasználónév információt és a 201-es státuszkódot, ami azt jelzi, hogy egy új erőforrás sikeresen létrejött.

Miért 201-es kóddal térünk vissza?

A 201 HTTP státuszkód jelentése "Created" (Létrehozva). Ezt a státuszkódot akkor használjuk, amikor egy HTTP kérés eredményeképpen új erőforrás jön létre a szerveren. A POST kérések esetén, amelyek új adatokat szúrnak be vagy új erőforrásokat hoznak létre (például egy új felhasználói profil létrehozása egy adatbázisban), a 201 státuszkód a legmegfelelőbb válasz, mert pontosan tükrözi a művelet eredményét.

A 201 kód használata az alábbiakat kommunikálja a kliens számára:

  • A kérés sikeres volt.
  • Egy új erőforrás létrejött.
  • A válasz általában tartalmaz egy Location fejlécet, ami az újonnan létrehozott erőforrás URI-ját (egyedi erőforrás-azonosítót) tartalmazza, bár ezt nem minden alkalmazás implementálja vagy szükséges megadni. Ezzel szemben, ha csak egy egyszerű módosítást hajtunk végre egy már létező erőforráson (például egy felhasználói profil frissítése), akkor gyakran a 200 (OK) vagy 204 (No Content, ha a válasz nem tartalmaz tartalmat) státuszkódokat használjuk.

Az általunk megadott kontextusban, ahol egy új felhasználó rekordot szúrunk be az adatbázisba, a 201 státuszkód a helyes válasz, mivel ez pontosan tükrözi, hogy a kérés során létrejött egy új erőforrás.

Tesztelés

A POST metódust tesztelni böngészőben közvetlen nem lehet. A teszteléshez használjuk például a Postman programot az alábbi konfigurációval:

  • URL: http://127.0.0.1:5000/users
  • Metódus: POST
  • Body: raw típusú, JSON formátumú:
Body tartalma
1
2
3
4
{
    "email": "Új email",
    "password": "Új jelszó"
}

Postman POST példa

Végpont adafrissítéshez

Emlékeztető

Az adatbázis módosításához a PUT metódust használjuk.

Az alábbi kód egy adott e-mail cím alapján frissíti a felhasználó jelszavát. Amennyiben nincs olyan felhasználó, akinek az e-mail címe megegyezik a paraméterben kapott e-mail címmel, akkor egy 404-es hibát ad vissza egy hibaüzenettel. Ha volt érintett sor, akkor egy 200-as státuszkóddal visszatérési értékként egy sikeres választ ad vissza.

@app.route('/users/<email>', methods=['PUT']) #(1)
def update_user(email): #(2)
    data = request.json #(3)
    new_password = data['password'] #(4)

    connection =  sqlite3.connect(db) #(5)
    cursor = connection.cursor() #(6)
    cursor.execute("UPDATE users SET password = ? WHERE email = ?", [new_password, email]) #(7)
    modositott_sorok = cursor.rowcount #(8)
    connection.commit() #(9)
    connection.close() #(10)

    if modositott_sorok == 0: #(11)
        return jsonify({'error': 'Nincs ilyen felhasználó!'}), 404 #(12)
    else:
        return jsonify({'success': True}), 200 #(13)
  1. Deklarálja az útvonalat (/users/<email>) egy PUT metódus számára, ami azt jelenti, hogy a kód ezen része egy felhasználó adatainak frissítésére szolgál.
  2. Definiál egy függvényt, update_user, amely fogad egy email paramétert az URL-ből.
  3. Kinyeri a kérés JSON tartalmát, amely az új jelszót tartalmazza.
  4. Kinyeri az új jelszót a JSON adatokból.
  5. Kapcsolódik az users.sqlite adatbázishoz.
  6. Létrehoz egy kurzort, amely lehetővé teszi az adatbázisban való műveletek végrehajtását.
  7. Végrehajt egy SQL frissítési műveletet, amely frissíti a felhasználó jelszavát, ha az email cím megegyezik.
  8. Lekéri az érintett sorok számát a frissítés után.
  9. Véglegesíti (commit) az adatbázis-műveletet.
  10. Bezárja az adatbázis-kapcsolatot.
  11. Ellenőrzi, hogy volt-e érintett sor a frissítés során.
  12. Ha nem volt érintett sor (nincs ilyen felhasználó), akkor egy 404-es hibát ad vissza egy hibaüzenettel.
  13. Ha volt érintett sor, sikeres választ küld vissza (200-as státuszkóddal).

Tesztelés

PUT metódust tesztelni böngészőben nem lehet, mert a böngésző csak GET és POST metódusokat támogat. A teszteléshez asználjuk például a Postman programot az alábbi konfigurációval:

  • URL: http://127.0.0.1:5000/users/johndoe@mail.com
  • Metódus: PUT
  • Body: raw típusú, JSON formátumú:
Body tartalma
1
2
3
{
    "password": "Új jelszó"
}

Postman példa

Végpont törléshez

Emlékeztető

Az adatbázisból való törléshez a DELETE metódust használjuk.

Az alábbi kód egy adott e-mail cím alapján törli a felhasználót az adatbázisból. Amennyiben nincs olyan felhasználó, akinek az e-mail címe megegyezik a paraméterben kapott e-mail címmel, akkor egy 404-es hibát ad vissza egy hibaüzenettel. Ha volt érintett sor, akkor egy 200-as státuszkóddal visszatérési értékként egy sikeres választ ad vissza.

@app.route('/users/<email>', methods=['DELETE']) #(1)
def delete_user(email): #(2)
    connection =  sqlite3.connect(db) #(3)
    cursor = connection.cursor() #(4)
    cursor.execute("DELETE FROM users WHERE email = ?", [email]) #(5)
    modositott_sorok = cursor.rowcount #(6)
    connection.commit() #(7)
    connection.close() #(8)

    if modositott_sorok == 0: #(9)
        return jsonify({'error': 'Nincs ilyen felhasználó!'}), 404 #(10)
    else:
        return jsonify({'success': True}), 200 #(11)
  1. Útvonal deklarálása DELETE metódussal: Ez jelzi, hogy az útvonal a felhasználó törlésére szolgál az email cím alapján.
  2. Függvény definíciója: A delete_user függvény egy email cím paramétert fogad, amely alapján törölni kíván egy felhasználót.
  3. Adatbázis-kapcsolat létrehozása: Kapcsolódik az users.sqlite adatbázishoz, hogy hozzáférjen a felhasználói adatokhoz.
  4. Kurzor létrehozása: Egy kurzort hoz létre az adatbázisban való műveletek elvégzéséhez.
  5. Törlési művelet végrehajtása: Törli a megadott email címmel rendelkező felhasználót az adatbázisból.
  6. Érintett sorok számának lekérdezése: Meghatározza, hogy a törlési művelet során hány sor került ténylegesen törlésre.
  7. Változások véglegesítése: A műveletet követően véglegesíti a változásokat az adatbázisban, biztosítva a törlés állandóságát.
  8. Adatbázis-kapcsolat bezárása: A művelet befejeztével bezárja az adatbázis-kapcsolatot.
  9. Sorok érintettségének ellenőrzése: Ellenőrzi, hogy az adatbázis-művelet során történt-e sor törlése.
  10. Hibaüzenet küldése, ha nincs ilyen felhasználó: Ha az érintett sorok száma nulla, vagyis nincs ilyen email címmel rendelkező felhasználó, akkor egy 404-es hibakódot küld vissza egy hibaüzenettel.
  11. Sikeres válasz küldése, ha a törlés megtörtént: Ha az érintett sorok száma nem nulla, vagyis sikeresen történt a törlés, akkor egy sikeres választ küld vissza 200-as státuszkóddal.

Tesztelés

A DELETE metódust tesztelni böngészőben közvetlen nem lehet. A teszteléshez használjuk például a Postman programot az alábbi konfigurációval:

  • URL: http://127.0.0.1:5000/users/janedoe@mail.com:
  • Metódus: DELETE
  • Body: none típusú

Postman DELETE példa

Postman

A fentiekben elkészített példa után a Postman programban a következőképpen néz ki az általunk létrehozott kollekció, amelyet ide kattintva le is tölthetsz:

Postman kollekció

Ezt természetesen ki is exportálhatjuk, hogy mások is használhassák a kollekciót. Az exportálás a következőképpen történik:

  1. Kattintsunk a Backend_teszt feliratra
  2. Kattintsunk az Export gombra
  3. Fogadjuk el a Collection v2.1 formátumot
  4. Válasszuk ki a projekt könyvtárat ahol a Python fájl is található