Skip to content

Flask - Erste Schritte

Allgemeine Diskussionen
  • Ich habe ja meine letzten kleineren Projekte mit Pywebio gemacht. Aber, so langsam komme ich damit an seine Grenzen. Da fiel mir ein, das es für Python auch noch andere Frameworks gibt. Zwei die mir spontan einfielen waren

    Ich hatte beide schon mal getestet, aber da waren meine Python Kenntnisse noch sehr begrenzt. Mittlerweile bin ich da schon ein Stück weiter. Django machte damals den komplizierten Eindruck, so das meine Wahl auf Flask fiel.

    Da man heute einen prima Personal Trainer hat, ChatGPT, habe ich diesen mal gebeten mir ein kurzes Beispiel zu generieren. Grundlage ist meine private Aktienverwaltung, die auf der ersten Seite mein Depot anzeigt usw. Die Kurse scrape ich von einer Webseite usw.

    Kurze Zeit später hatte ich ein funktionierendes Beispiel, das ich bis jetzt gut ausgebaut habe. Da Flask den Logikteil vom HTML-Teil sehr gut trennt, kann man das relativ einfach überblicken. Nach kurzem Ausprobieren, hatte ich das Konzept in seinen Grundzügen verstanden.

    Der Anfang sah so aus.

    app.py

    from flask import Flask, render_template
    
    app = Flask(__name__)
    
    # Sample data for our table
    DATA = [
        {"id": 1, "name": "John", "email": "john@example.com"},
        {"id": 2, "name": "Jane", "email": "jane@example.com"},
        {"id": 3, "name": "Doe", "email": "doe@example.com"}
    ]
    
    @app.route('/')
    def index():
        return render_template('index.html', data=DATA)
    
    if __name__ == "__main__":
        app.run(debug=True)
    

    templates/index.html

    <!DOCTYPE html>
    <html>
    <head>
        <title>Flask Table Example</title>
    </head>
    <body>
        <!-- Navigation Menu -->
        <ul>
            <li><a href="#">Menu 1</a></li>
            <li><a href="#">Menu 2</a></li>
            <li><a href="#">Menu 3</a></li>
            <li><a href="#">Menu 4</a></li>
            <li><a href="#">Menu 5</a></li>
        </ul>
    
        <!-- Table Displaying Data -->
        <table border="1">
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Email</th>
                </tr>
            </thead>
            <tbody>
                {% for row in data %}
                <tr>
                    <td>{{ row.id }}</td>
                    <td>{{ row.name }}</td>
                    <td>{{ row.email }}</td>
                </tr>
                {% endfor %}
            </tbody>
        </table>
    </body>
    </html>
    
    

    Mittlerweile ist das mein Stand

    2b147097-c888-447e-8fc4-acd7f459d666-grafik.png

    Daten kommen aus einer Redis Datenbank usw. Vielleicht stelle ich das mal hier vor, wenn es "fertig" ist. Liest hier einer mit, der auch Flask nutzt?

  • Ok, ich benutze eine Funktion die sich die aktuellen Kurs abholt. Das habe ich in Pywebio mit

    put_loading()
    

    gemacht. Dafür brauche ich jetzt eine Alternative. Mir kam da in den Sinn, das mit asyncio zu machen. Den Test aus der Flask Doku ausprobiert.

    @app.route("/get-data")
    async def get_data():
        data = await async_db_query(...)
        return jsonify(data)
    

    Leicht abgewandelt in

    @app.route('/refresh', methods=['POST'])
    async def refresh():
        import time
        time.sleep(5)
        return jsonify("TEST")
    

    Kommt beim Testen die Fehlermeldung das async erst ab Version 2.0 unterstützt wird und auch nur, wenn Flask mit async installiert wurde 🤔

    Ok, kurz recherchiert. Man muss Flask mit der Option async installieren.

    (venv) frank@debian:~/PycharmProjects/flask$ pip install Flask[async]
    Requirement already satisfied: Flask[async] in ./venv/lib/python3.11/site-packages (3.0.0)
    Requirement already satisfied: Werkzeug>=3.0.0 in ./venv/lib/python3.11/site-packages (from Flask[async]) (3.0.0)
    Requirement already satisfied: Jinja2>=3.1.2 in ./venv/lib/python3.11/site-packages (from Flask[async]) (3.1.2)
    Requirement already satisfied: itsdangerous>=2.1.2 in ./venv/lib/python3.11/site-packages (from Flask[async]) (2.1.2)
    Requirement already satisfied: click>=8.1.3 in ./venv/lib/python3.11/site-packages (from Flask[async]) (8.1.7)
    Requirement already satisfied: blinker>=1.6.2 in ./venv/lib/python3.11/site-packages (from Flask[async]) (1.6.3)
    Collecting asgiref>=3.2 (from Flask[async])
    

    Danach ging mein Beispiel und es kam 5 Sekunden später folgende Anzeige im Webbrowser.

    9753d07e-a2ce-47a7-9be0-c2010684b725-grafik.png

    Dann kann ich jetzt weiter spielen..

  • Mein vorhandenes Projekt war doch etwas größer als ich gedacht hatte. Also musste ich mehr Zeit aufwenden um es nach Flask zu transferieren. Nach einiger Zeit hatte sich eine ganz ansehnliche Zahl von Dateien angesammelt und es kam wie es kommen musste, ich wusste manchmal nicht mehr, welches File ich anfassen musste. Chaos kam auf 🙂

    So fing ich an ein wenig zu recherchieren und kam auf die Funktion Blueprint von Flask. Mich ein wenig eingelesen, ChatGPT mal eben um ein Beispiel gebeten und dann angefangen die Applikation entsprechend umzubauen.

    Auch das hat Zeit gekostet. Aber, jetzt habe ich ein aufgeräumtes Projekt, was es mir wesentlich einfacher macht, daran zu arbeiten.

    5226e90d-aa20-4b20-93af-e50f8f841880-grafik.png

    Wenn ihr also mal vorhabt, so was zu coden, halte ich es für sinnvoll das Projekt von Anfang an zu strukturieren. Und zum Schluss noch ein Screenshot zum Stand des Projektes.

    a7981ffc-0f93-41f4-93e2-c914fdba5e43-grafik.png

    Und weiter geht es, ist nämlich noch nicht fertig 😀

  • 0 Stimmen
    1 Beiträge
    84 Aufrufe
    Niemand hat geantwortet
  • List comprehensions

    Python3
    1
    0 Stimmen
    1 Beiträge
    58 Aufrufe
    Niemand hat geantwortet
  • Example Class

    Angeheftet Python3
    3
    0 Stimmen
    3 Beiträge
    104 Aufrufe
    FrankMF

    In meinem PywebIO Projekt tauchte heute ein alter Bekannter auf. Wenn ich einen Eintrag (innerhalb der Liste) löschte, war das etwas durcheinander 🤔

    Ja, den Fehler kenne ich schon was länger und stolper immer mal wieder drüber. Heute z.B.

    Also mal grübeln 🤓

    Das mache ich, wenn ich einen Eintrag lösche

    case 'Yes': # delete entrie BackupList.delete((line - 1)) # save json BackupList.save_json() # Load data from filesystem BackupList.load_json() # Reload Tab Backup backup()

    Ich mache folgendes

    lösche den Eintrag speicher die Liste lade die Liste baue den Tab wieder auf

    Das führt aber dazu, das meine Liste die als Objekt im Speicher steht nicht aktuell ist. Im Gegenteil, da ist dann etwas Unordnung. Ich brauchte also die Möglichkeit mein Objekt backups irgendwie zurückzusetzen.

    Mal gegoogelt und die Dinge sind manchmal wirklich total easy 🙂

    # clear dict backups.clear()

    Das leert das Objekt und im nächsten Schritt kann ich es wieder befüllen.

    Lösung case 'Yes': # delete entrie BackupList.delete((line - 1)) # save json BackupList.save_json() # clear dict backups.clear() # Load data from filesystem BackupList.load_json() # Reload Tab Backup backup()

    Problem erledigt. Damit ich das noch finde, wenn mein Kopf das nicht mehr hergibt, notiere ich das hier.

  • Python - Dict -> JSON und umgekehrt

    Python3
    1
    0 Stimmen
    1 Beiträge
    199 Aufrufe
    Niemand hat geantwortet
  • PyWebIO - put_buttons

    PyWebIO
    2
    0 Stimmen
    2 Beiträge
    147 Aufrufe
    FrankMF

    Und noch eine kleine Übung, wie man den Buttton abhängig von einem Value enabled/disabled

    # we build header and tdata for table tab_mount = [] for count, value in enumerate(backups): if count == 0: tab_mount.append(['No.', 'Backup name of the restic data backup', 'Actions']) if backups[value].init == "0": tab_mount.append([count + 1, backups[count].name, put_buttons([ dict(label='Mount', value='Mount', color='primary', disabled=True), dict(label='UMount', value='UMount', color='primary', disabled=True), dict(label='Restore', value='Restore', color='primary', disabled=True), ] , onclick=partial(actions, count + 1)) ]) else: tab_mount.append([count + 1, backups[count].name, put_buttons([ dict(label='Mount', value='Mount', color='primary'), dict(label='UMount', value='UMount', color='primary'), dict(label='Restore', value='Restore', color='primary'), ], onclick=partial(actions, count + 1)) ])
  • PyWebIO

    Angeheftet PyWebIO
    1
    0 Stimmen
    1 Beiträge
    163 Aufrufe
    Niemand hat geantwortet
  • Python3 - VSCodium Language Settings

    Python3
    3
    0 Stimmen
    3 Beiträge
    112 Aufrufe
    FrankMF

    Ich habe da jetzt gestern stundenlang mit rum gespielt, insbesondere Deinstallation, Neuinstallation, VSCode Installation usw. Das ging einfach nicht.

    Irgendwo meine ich dann gelesen zu haben, das VSCode auf python 3.9 festgenagelt ist und deswegen so einige Dinge nicht gehen.

    Nagelt mich darauf nicht fest, ich bin in dieser Coding Welt kein Profi.

    Dann fiel mir ein, das ich schon vor einigen Monaten mal kurz einen Blick in Pycharm geworfen hatte. Gefiel mir damals gar nicht.

    Das habe ich heute mal auf die Platte geworfen um zu schauen, ob das vernünftig mit dem o.g. Problem umgehen kann.

    6f1c3906-05a3-4126-81d4-7fdf6aa27faa-grafik.png

    Puuuh, da kann man ja noch viel mehr einstellen als bei VSCode, oder mindestens ähnlich viel. Das kann einen ganz schön überfordern. Also Stück für Stück die nächsten Tage.

    Was ist mir positiv aufgefallen?

    Wenn ich VSCodium neu installiert habe, habe ich unheimlich mit Python Versionen, pipenv usw. zu kämpfen gehabt. Bis da mein Projekt wieder lief, konnte schon mal was Zeit vergehen.

    Mit Pycharm Ordner ausgewählt, angeklickt das man dem Coder vertraut. Noch eine Python Version ausgewählt, danach fragt er das er eine pipenv Umgebung gefunden hat und diese nutzen möchte. Ja angeklickt und fertig. Keine zwei Minuten und das Projekt lief wieder 🤓

    Erster Git Commit ging auch sofort und ohne Murren.

    Schon mal ganz viele Pluspunkte gesammelt.

    Was mich aktuell beschäftigt, ist der Tab Problems, da hatte ich vorher deutlich weniger. Da muss ich mich noch was einarbeiten und schauen, wo man das alles einstellen kann.

    Ich halte euch auf dem Laufenden..

    Vielleicht fliegt ja das VSCo** Zeug runter!? Mal sehen..

  • PyQt6 - QSettings

    Python3
    3
    0 Stimmen
    3 Beiträge
    218 Aufrufe
    FrankMF
    Möglichkeit 1

    Das hier

    settings = QSettings("Frank_Mankel", "Restic_UI")

    erzeugt unter

    /home/frank/.config/Frank_Mankel/Restic_UI.conf

    die Konfigurationsdatei.

    Möglichkeit 2

    Das hier

    settings = QSettings("Restic_UI")

    erzeugt unter

    /home/frank/.config/Restic_UI.conf

    die Konfigurationsdatei.

    Damit habe ich die grundlegenden Dinge, hoffentlich 😉 , verstanden.

    Für den Rest mal in die Dokumentation schauen.

    Sehr hilfreich war auch mal ein Blick auf die Definition der Klasse. Rechtsklick auf QSettings und dann Go to Definition

    class QSettings(QObject): class Scope(enum.Enum): UserScope = ... # type: QSettings.Scope SystemScope = ... # type: QSettings.Scope class Format(enum.Enum): NativeFormat = ... # type: QSettings.Format IniFormat = ... # type: QSettings.Format InvalidFormat = ... # type: QSettings.Format class Status(enum.Enum): NoError = ... # type: QSettings.Status AccessError = ... # type: QSettings.Status FormatError = ... # type: QSettings.Status [..gekürzt..]