Flask Python-Funktion an Template übergeben

Django, Flask, Bottle, WSGI, CGI…
Antworten
Benutzeravatar
mobby
User
Beiträge: 76
Registriert: Donnerstag 17. April 2014, 09:43

Hi,

Ich stehe vor folgendem Problem, ich möchte aus meinem HTML Template Python Funktionen aufrufen. Z.B. Datenbankeinträge mittels JavaScript aktualisieren. Und zwar ohne ein POST Request abzugeben. Im Folgenden ein simples Beispiel, wie ich es bisher angegangen bin.

Core.py

Code: Alles auswählen

app = Flask(__name__)

@app.context_processor
def processor():
    def test(value):
        print value
        return value
    return dict(test=test)

Index.html

Code: Alles auswählen

<button type="button" onclick="test()">Test</button>

<script>
function test() {
    {{ test(23) }}
}
</script>
Leider wird die Python Funktion beim Aufruf der Seite / GET Request bereits aufgelöst/ausgeführt. Auch durch weiteres Klicken auf den Button wird die Funktion leider nicht erneut getriggert. Bin ich hier auf dem Holzweg? Falls ja, wie könnte ich dieses Problem lösen?

Vielen Dank für Rückmeldung und viele Grüße
mobby
BlackJack

@mobby: Wenn Du keine POST-Abfrage durchführen möchtest, dann nimm halt eine GET-Abfrage. ;-)

Wie Du schon richtig bemerkt hast wird Python auf dem Server ausgeführt um das HTML zu erstellen was dann zum Client gesendet wird. Und genau das ist die Grenze. Python ist auf dem Server, wenn die Daten zum Client gesendet werden ist's mit Python vorbei, dann ist die Anfrage abgearbeitet. Um danach erneut Python auf dem Server auszuführen, braucht's eine neue Anfrage. Warum willst Du da keinen Ajax-Aufruf machen?
Benutzeravatar
mobby
User
Beiträge: 76
Registriert: Donnerstag 17. April 2014, 09:43

@BlackJack: Vielen Dank für die Antwort, war mir irgendwie schon klar mit der Server/Client Beziehung. Aber habe mir gedacht, vielleicht gibt es ja doch etwas auf das ich noch nicht gekommen bin ;).

Ajax habe ich schon auf dem Schirm. Allerdings triggert das am Ende ja auch nur GET/POST. Zudem hatte ich bisher ein Problem mit Ajax, nachdem ich z.B. eine POST Anfrage abgesendet habe, ließ sich auf Serverseite keine Weiterleitung triggern.

Allerdings habe ich noch eine andere Frage, die mein Problem vielleicht auch lösen kann. Gibt es eine Möglichkeit Aktionen beim Verlassen einer Seite zu triggern? Z.B. ich öffne Index via GET und es wird mein Template wiedergegeben usw., jetzt verlasse ich Index über eine GET Anfrage einer anderen Seite z.B. Login. Kann ich über Flask Anwendungs-Decorator Aktionen auf das Verlassen einer Seite binden? Ich hoffe ich konnte verständlich machen um was es mir geht. Hintergrund des Ganzen ist, dass ich HTML Input Elemente auf einer Seite habe und den Inhalt gerne automatisch an Python übergeben möchte, sobald ich die Seite verlasse. Somit würde ich mir den Button für einen Reload via GET/POST sparen.
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Es gibt mehrere Möglichkeiten einen POST weiterzuleiten, teilweise wird dabei aus dem POST ein GET. Schau dir da genau an welche Status Codes du verwendest und was deren exakte Bedeutung ist. Um einen Überblick zu bekommen was Server und Client eigentlich machen, kann es vielleicht auch hilfreich sein sowas wie mitmproxy zu verwenden.

Mit GET wird ein HTTP Server nach einem Dokument gefragt. Es wird *nicht* eine Seite verlassen auch nicht implizit. Der User könnte ja von einem anderen Tab aus auf deine Seite zugreifen oder seinem Handy weil er grad von seinem Desktop aufgestanden ist und mit dem Handy auf dem Klo weitersurft um später am Desktop an derselben Seite weiterzuarbeiten wo er aufgehört hat.

Wie BlackJack schon erwähnt hat es gibt einen Unterschied zwischen Client und Server. Du magst dir dem irgendwo bewusst sein aber verinnerlicht hast du dir dass noch nicht so ganz. Wenn du möchtest darauf zu reagieren dass eine Seite verlassen wird, kannst du dies per JS mit dem beforeunload Event tun.

Was du vorhast ist aber so ohnehin nicht sinnvoll. Speichere die aktuellen Eingaben als Entwurf alle n Sekunden noch während der User die Seite nutzt. Auf die Weise verlierst du die Daten nicht nur beim schliessen der Seite nicht, sondern auch in anderen Szenarien wie Verlust der Internetverbindung, Absturz des Browser usw.
BlackJack

Statt alle n Sekunden würde ich eher nach Änderungen oder alle n Sekunden nur falls sich etwas geändert hat nehmen. Sonst sendet ein Reiter den man offen, aber ”vergessen” hat, fröhlich den ganzen Tag sinnlos Daten. :-) Vielleicht ist sowas aber auch nur mein Problem. Grad mal im Session-Manager-Plugin nachgeschaut: 422 Seiten sind da gerade bei mir ”offen”…
Benutzeravatar
mobby
User
Beiträge: 76
Registriert: Donnerstag 17. April 2014, 09:43

@DasIch: Danke für die Tipps, werde ich mir anschauen.

Vielleicht noch mal einfacher zusammengefasst was ich eigentlich suche. Ich sende eine GET Anfrage an meinen HTTP Server (in dem Fall Flask), über meinen Decorator @app.route('/') lege ich fest was bei Aufruf dieser GET Anfrage abgearbeitet wird. Typischerweise wird am Ende ein Template z.B. index.html wiedergegeben. Wenn dann alle Variablen, die ich dem Template mit auf dem Weg gegeben habe, aufgelöst sind ist meine Abfrage durch und ich habe eine statische Seite vor mir. Um auf der Client Seite Aktionen durchzuführen ohne weitere HTTP Abfragen zu triggern bleibt mir nur JavaScript. Und jetzt möchte ich irgendwie Daten (Formular Inhalte) über eine JS Funktion an meinen Server senden. Auf Server Seite wartet dann irgendein Prozess auf Daten und verarbeitet diese sobald sie ankommen (Z.B. Datenbankeinträge die unabhängig von der Client Seite erfolgen). Gibt es dazu eine Standardlösung in Flask oder muss man sich dazu etwas bauen?

@BlackJack: Diese JS-Funktion könnte man dann über die Änderung eines Eingabefeldes triggern.

Wäre so etwas vielleicht mit HTML5 Websockets lösbar?
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

mobby hat geschrieben:Um auf der Client Seite Aktionen durchzuführen ohne weitere HTTP Abfragen zu triggern bleibt mir nur JavaScript.
Um auf der Client Seite Aktionen durchzuführen bleibt dir nur JavaScript, unabhängig davon ob du weitere HTTP Abfragen machen möchtest oder nicht.
Und jetzt möchte ich irgendwie Daten (Formular Inhalte) über eine JS Funktion an meinen Server senden. Auf Server Seite wartet dann irgendein Prozess auf Daten und verarbeitet diese sobald sie ankommen (Z.B. Datenbankeinträge die unabhängig von der Client Seite erfolgen). Gibt es dazu eine Standardlösung in Flask oder muss man sich dazu etwas bauen?
Die JS Funktion die du suchst ist Ajax, also HTTP Requests, worauf du auf Flask Seite genauso reagierst wie auf alle anderen Requests auch.

Anstatt Ajax könnest du theoretisch auch Websockets nutzen, dies ist aber wesentlich komplizierter und lohnt sich eigentlich nur wenn der Server unabhängig vom Client etwas sendet oder du mit so hoher Frequenz (öfter als einmal pro Sekunde) Daten an den Server sendest, dass der Overhead vom Verbindungsaufbau dich ausbremst.
Benutzeravatar
mobby
User
Beiträge: 76
Registriert: Donnerstag 17. April 2014, 09:43

@DasIch: Super danke, dann mach ich mich mal an die Arbeit. Ich berichte, wenn es was geworden ist :).
Antworten