Flask Jinja Var Count + 1 in For Loop

Django, Flask, Bottle, WSGI, CGI…
Antworten
bst2k
User
Beiträge: 10
Registriert: Mittwoch 6. Februar 2019, 18:50

Hallo zusammen,

Code: Alles auswählen

    {% set anf = 1 %}

    {% for c in stationCount %}

        <p>{{anf}}</p>

        {% set anf = anf + 1 %}

    {% endfor %}
die Variable 'anf' sollte doch hier immer um 1 erhöht werden, wo liegt mein Fehler? Es wird immer nur die Variable vor der For Schleife ausgegeben, sprich immer nur die 1.
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Grundsätzlich ist das richtig.
Ob und wie oft die for-Schleife ausgeführt wird, hängt abr von stationCount ab.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bst2k: Und man würde das auch nicht selbst machen — es gibt ja das `loop`-Objekt und dessen `index`-Attribut:

Code: Alles auswählen

    {% for c in stationCount %}
        <p>{{loop.index}}</p>
    {% endfor %}[/url]
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
bst2k
User
Beiträge: 10
Registriert: Mittwoch 6. Februar 2019, 18:50

Vielen Dank erstmal für die Antworten, dann frage ich mich, wieso dennoch immer nur die 1 ausgegeben wird.

Das nur ein Test Snippet, weil die richtige Berechnung nicht funktioniert hat und ich versucht habe dem ganzen auf die Schliche zu kommen.

Im Prinzip versuche ich folgendes zu bewerkstelligen:

In einer MySQL Datenbank stehen einige Datensätze, die Anzahl der verschiedenen 'stationen' ist, genau wie die Anzahl der Datensätze, immer unterschiedlich.

Jetzt möchte ich natürlich nicht 50 Parameter übergeben müssen, daher setze ich alles in eine Liste und übergebe diese. In 'stationCount' ist die Anzahl des Datensatzes für jede der 26 Stationen hinterlegt. Da ich diese Liste aber im HTML Dokument einzeln auflisten möchte, und ich ja die Anzahl des jeweiligen Datensatzes kenne, wollte ich es dann wie folgt aufsplitten:

Code: Alles auswählen

    {% set anf = 0 %}
    {% set end = 0 %}

    {% for c in stationCount %}

        {% set end = anf + c %}

        <p>{{station[anf:end]}}</p>

        {% set anf = end + 1 %}

    {% endfor %}
stationCount sieht wie folgt aus:

Code: Alles auswählen

[72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 72, 64, 67, 66, 64, 64, 63, 52, 63, 60, 56, 56, 44]
Da sich aber die Variablen nicht wie erwartet erhöhen, funktioniert es leider nicht. Woran könnte es denn liegen, dass sich die Var's nicht erhöhen?

Danke nochmal!
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@bst2k: Jinja ist keine Programmiersprache. Mach das, was Du willst in Python und über gib dem Template einfach eine Station-Liste.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bst2k: Beschreibung, Variablenname, und der Code machen alle irgendwie keinen Sinn. `Count` deutet tatsächlich auf Anzahlen hin, aber „die Anzahl des jeweiligen Datensatzes für jede der 26 Stationen“ macht keinen Sinn. Wie kann denn ein Datensatz für eine Station eine Anzahl haben? Was wird denn da gezählt?

Lass Dir mal `anf` und `end` ausgeben und die Länge von `stationen` – ich wette Du hast da schon 26 <p>-Elemente im Ergebnis, aber `anf` und `end` werden wahrscheinlich schon nach dem ersten mal so gross sein, dass da nur noch leere „slices“ bei heraus kommen.

Wenn Du das im Python-Code statt im Template löst, könnte eventuell `more_itertools.split_into()` interessant sein. Sofern ich das Problem richtig erraten habe.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
bst2k
User
Beiträge: 10
Registriert: Mittwoch 6. Februar 2019, 18:50

@blackjack:

Die Tabelle enthält folgende Daten:

ID, Datum, StationsID, Region, Umsatz

In die Tabelle werden alle 15 Minuten neue Daten eingespielt.

In dem oberen Beispiel enthält enthält die Tabelle unter "StationsID" 26 verschiedene Stationen, also für 26 Stationen werden alle 15 Minuten neue Daten eingespielt.

Wenn ich in MySQL nacheinander nach der "StationsID" sortiere, habe ich für Station1 also 72 Einträge und für Station15 nur 64 Einträge - das ist die Bedeutung der Zahlen aus stationCount.

In Python könnte ich jetzt 26 Variablen übergeben, das müsste ich aber fix schreiben, oder geht das auch Dynamisch? In der nächsten Tabelle wären es zB. nur noch 12 Stationen und im anderen dann 50. Daher kam ich auf die Idee, einfach alles zusammen in eine Liste zu werfen und diese Liste zu übergeben. Das sieht wie folgt aus:

Code: Alles auswählen

['StationsID1', 5000, 5000, *70 weitere Einträge 'StationsID2', 6000, 7000, *64 weitere Einträge, usw usw]
Das wollte ich dann in Jinja wieder auseinander nehmen, so dass ich dann wieder alle einzelnen Einträge für die jeweilige Station rausbekomme.

Lass Dir mal `anf` und `end` ausgeben und die Länge von `stationen` – ich wette Du hast da schon 26 <p>-Elemente im Ergebnis, aber `anf` und `end` werden wahrscheinlich schon nach dem ersten mal so gross sein, dass da nur noch leere „slices“ bei heraus kommen.
Nein leider nicht, die erste Zahl ist immer die 0 und die zweite ist der Wert aus der stationCount Liste.

Code: Alles auswählen

0

72

0

64

0

67

0

66

0

64
Deswegen hatte ich den Code aus meinem ersten Post getestet, weil die Variablen einfach nicht hochgezählt werden.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bst2k: Das ist keine gute Idee das so in einer Liste zusammen zu werfen, denn dann muss man das ja wieder zerlegen. Und das dann auch noch mit Informationen aus zwei Listen. Wie kommt man auf so umständliche Sachen? Am allereinfachsten wäre es wahrscheinlich gar keine Liste mit Werten selbst zu erstellen, sondern einfach das nach Stations-ID sortiere Ergebnis der Abfrage an das Template zu übergeben und im Template zwei Schleifen zu verschachteln, wobei man bei der äusseren `groupby` im Template verwendet um nach den Stations-IDs zu gruppieren.

Und ich sehe nicht wie bei den gegebenen Werten eine der beiden Template-Variablen immer 0 bleiben kann.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
bst2k
User
Beiträge: 10
Registriert: Mittwoch 6. Februar 2019, 18:50

@blackjack: Du wirst sicher schnell sehen, dass ich mich noch nicht soo lange und intensiv mit Python/Flask beschäftigte, ich freue mich also über jede konstruktive Kritik.

Code: Alles auswählen

for st in stationen:

    mycursor = mysql.get_db().cursor()
    mycursor.execute("SELECT * FROM " + st + " WHERE StationsID = '"+ staID +"' AND Datum >= '" + startDatum + " 00:00:00' AND Datum <= '" + endDatum + " 23:59:49'")
    data = mycursor.fetchall()

    if ZeitSpam == False:
            zeit = [""]
            for z in data:
                    t = z[1].strftime("%H%M")
                    zeit.append(t)
            ZeitSpam = True

    x = 0
    for d in data:
            u = d[9]
            x = x + 1
            station.append(u)

    count = len(station)
    c = count - x
    stationCount.append(x)
    station.insert(c, d[3] + ", " + d[4] + ", " + d[6])

return render_template('test.html', zeit=zeit, station=station, stationCount=stationCount)
Am Ende will ich mit Hilfe von Charts.js das ganze Darstellen, daher brauche ich die Einzelnen Daten.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@bst2k: Okay, da muss man ja ganz vorne Anfangen: Eine Tabelle pro Station ist falsch. Tabellennamen sind nichts was variabel sein sollte. Man speichert die Werte für alle Stationen in *einer* Tabelle. Wobei mir jetzt auch nicht so ganz klar ist was die `StationsID` *in* der jeweiligen Tabelle bedeuten soll‽

Das nächste ist das man Werte nicht mit Zeichenkettenoperationen in eine SQL-Abfrage hinein formatiert. Dafür gibt es Platzhalter und das zweite Argument von `execute()`.

SQL kennt den Operator BETWEEN.

Sternchen bei SELECT sind blöd weil man a) im Quelltext nicht sieht was denn da nun im Ergebnis steht, und b) Probleme mit dem Code bekommt wenn man Änderungen an der Tabellenstruktur vornimmt.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
bst2k
User
Beiträge: 10
Registriert: Mittwoch 6. Februar 2019, 18:50

Vielen Dank erstmal für deine Zeit und dein Feedback!

Für 'Stationen' gibt es vorher noch eine Abfrage aus einer Übersicht. Da die ID's relativ lang sind und man nicht eindeutig erkennen kann welcher Standort hinter der ID steckt, gibt es noch eine Match-Tabelle. Hier gibt es also auch keine variablen Tabellennamen.

Es gibt einen Standort den man auswählt = st

Ganz Plump gesagt, die StationID kann man mit verschiedenen Abteilungen vergleichen.

Beispiel:

Ich wähle den Standort Frankfurt. In Frankfurt gibt es dann noch die StationID's Sachsenhausen, Westend, Bonames usw. - jede StationsID bekommt alle 15 Minuten einen Umsatzwert.


Datum, StationsID, Umsatz
10.06.19 5:00 Sachsenhausen 5000
10.06.19 5:00 Westend 1000
10.06.19 5:00 Bonames 9000
10.06.19 5:15 Sachsenhausen 7000
10.06.19 5:15 Westend 4000
10.06.19 5:15 Bonames 3000
10.06.19 5:30 Sachsenhausen 1000
10.06.19 5:30 Westend 4000
10.06.19 5:30 Bonames 5000

usw.

Jetzt sollen für die jeweiligen StationID's alle Umsätze in eine Liste übertragen werden, die ich dann an Charts.js übergeben kann um die jeweiligen Graps erstellen zu lassen.

Da es mal 12, 20, 40 oder mehr StationID's sein können, kann ich die Variablen natürlich nicht fest programmieren.

Wie würdest du dies denn am effektivsten übergeben?


PS: Gerade nochmnal etwas getestet:

Code: Alles auswählen

{% set bla = 20 %}
<p>{{bla}}</p>
{% set bla = bla + 20 %}
<p>{{bla}}</p>
{% set bla = bla + 20 %}
<p>{{bla}}</p>
{% set bla = bla + 20 %}
wenn ich das so ausführe wird hochgezählt, wenn ich das ganze in einer For Schleife mache, nicht - wieso?

Code: Alles auswählen

{% set bla = 20 %}

{% for b in stationCount %}
    <p>{{bla}}</p>
    {% set bla = bla + 20 %}
{% endfor %}
Hier wird immer nur die 20 ausgegeben.
Benutzeravatar
sparrow
User
Beiträge: 4165
Registriert: Freitag 17. April 2009, 10:28

Wenn du nicht für jede Station eine Tabelle hast, warum hast du dann für jede Station eine eigene Abfrage mit einem speziellen Tabellennamen? Da scheint das Design der Datenbank, wie __blackjack__ schon sagte, kaputt zu sein.

Das, was du gerade versuchst in Jinja zu tun, gehört eigentlich in den Python teil. Dort muss die Logik sitzen, die Daten entsprechend aufzubereiten. Nicht in Jinja.

Zeig ein einfaches Beispiel mit einer Handvoll Daten und wie sie hinterher an das JavaScript übergeben werden sollen.

In Jinja gräbst du auf jeden Fall an der falschen Stelle.
Sirius3
User
Beiträge: 17712
Registriert: Sonntag 21. Oktober 2012, 17:20

@bst2k: die StationsID ist also gar keine ID, sondern ein Name, der für verschieden Standorte mehrfach vorkommen kann. Die Standorte sind die Variable, die Du in den Tabellennamen kodiert hast.
Dann verstehe ich aber nicht, woher ›staID‹ kommt?

Die Tabelle sollte also den Aufbau haben:
Datum, Standort, StationsID, Umsatz
Was sind denn die anderen sieben Felder, die Du hier per Index ansprichst?

Zum Code: wie __blackjack__ schon geschrieben hat, ist es total umständlich, eine Liste zu haben, in der die Daten stehen und eine zweite, wo die Anzahl der zusammengehörigen Einträge steht. Dafür nimmt man eine Liste, in der wieder Listen mit den Daten sind.
Eingerückt wird immer mit 4 Leerzeichen pro Ebene, nicht mal 4 und mal 8.
Variablennamen werden klein_mit_unterstrich geschrieben, und sind aussagekräftig. ›d‹ ist das definitiv nicht, und eine Variable, die ›Spam‹ im Namen hat, ...
Was soll das my bei ›mycursor‹? Gibt es auch noch einen yourcursor? Der Cursor kann vor der for-Schleife einmal erzeugt werden.

Was ist mit den letzten 10 Sekunden jeden Tages?

Für Variablen in SQL-Statements nimmt man Platzhalter. Das geht natürlich nicht für Tabellennamen, weil man ja auch keine variablen Tabellennamen benutzt.
Keinen * im SELECT und auch keine magischen Indexwerte im Programmcode. Statt dessen kann man die Einträge in Variablen entpacken.
Man vergleicht nicht explizit mit True oder False, sondern nimmt einfach die Variable, die ja schon einen Wahrheitswert darstellt oder dreht den Wert mit ›not‹ um.
Du gehst implizit davon aus, dass die Einträge aus der Datenbank immer in aufsteigender zeitlicher Reihenfolge geliefert werden. Das ist falsch. Sie kommen zufällig.

Die Tabelle ›station‹ scheint den Wert der an Index 9 steht zu enthalten und davor noch irgendwas das aus 3, 4 und 6 zusammengesetzt wird. Das ist wieder soetwas was man einfach nicht macht. Tabellen enthalten nur gleichartige Dinge. Wenn jedes x-te Element etwas anderes bedeutet, macht das die Verarbeitung sehr kompliziert und fehleranfällig.

Wenn ich raten soll, dann willst Du für jeden Standort und jede Station eine Liste mit den Umsätzen haben. Das bedeutet, Du mußt Deine Datenbankstruktur und Deine interne Datenrepräsentation genau auf diese Fragestellung anpassen:

Code: Alles auswählen

start_datum = datetime.datetime(2019, 8, 6)
end_datum = datetime.datetime(2019, 9, 6, 23, 59, 49)

cursor = mysql.get_db().cursor()
stationen_umsatz = defaultdict(list)
zeiten = []
cursor.execute("SELECT standort, station, datum, umsatz FROM umsatz WHERE datum BETWEEN %s AND %s ORDER BY datum", [start_datum, end_datum])
for standort, station, datum, umsatz in cursor:
    if not zeiten or zeiten[-1] != datum:
        # TODO: ensure, that the same times exist for each station.
        zeiten.append(datum)
    stationen_umsatz[standort, station].append(umsatz)

return render_template('test.html', zeiten=zeiten, stationen_umsatz=stationen_umsatz)
Nun hast Du ein Wörterbuch, dessen Schlüssel Standort und Station ist und dessen Werte eine Liste mit Umsätzen. Dieses Wörterbuch kannst Du nun einfach im Jinja-Template durchgehen und anzeigen.
Benutzeravatar
__blackjack__
User
Beiträge: 13006
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Ich habe übrigends gerade mal die Jinja2-Dokumentation gelesen. Sowohl bei ``for`` als auch bei ``set`` steht, dass der ursprüngliche Ansatz mit dem manuellen hochzählen nicht funktioniert. Variablen die in einer ``for``-Schleife definiert werden, werden am Ende des Schleifenblocks wieder gelöscht.
“Most people find the concept of programming obvious, but the doing impossible.” — Alan J. Perlis
bst2k
User
Beiträge: 10
Registriert: Mittwoch 6. Februar 2019, 18:50

Wow, Danke Blackjack!! :-)

Dein Code zeigt mir wie ich das ganze verkompliziert habe, jetzt funktioniert die Daten übergabe! :-)

Und auch der Jinja Fakt für die For Schleife ist Gold Wert.

Danke nochmals!
bst2k
User
Beiträge: 10
Registriert: Mittwoch 6. Februar 2019, 18:50

Sorry, natürlich Sirius, Blackjack und Sparrow ;-)

PS: Finde ich den Edit Button nicht, oder gibt es hier einfach keinen?
__deets__
User
Beiträge: 14494
Registriert: Mittwoch 14. Oktober 2015, 14:29

Doch, aber der geht nur für 15 Minuten oder so.
bst2k
User
Beiträge: 10
Registriert: Mittwoch 6. Februar 2019, 18:50

__deets__ hat geschrieben: Montag 10. Juni 2019, 21:53 Doch, aber der geht nur für 15 Minuten oder so.
Oh Ok Danke für die Info :-)
Antworten