Was ist der beste Weg, eine erzwungene Seitenaktualisierung mit Flask zu implementieren?
Lesezeit: 5 Minuten
Adam Lewis
Hintergrund
Ich habe eine große Anzahl von Feldern, die in Echtzeit von einem externen Prozess aktualisiert werden. Ich möchte die von Flask gehosteten Seiten regelmäßig aktualisieren, um verbundenen Benutzern alle Änderungen anzuzeigen. Im Idealfall würde nicht die gesamte Seite aktualisiert werden (dies war eine Beschwerde eines ähnlichen Systems), sondern nur eine Reihe von Feldern auf der Seite aktualisiert werden.
Aktuelle Richtung
Meine aktuellen Überlegungen sind, möglicherweise JavaScript zu verwenden, um damit umzugehen, aber ich bin mir nicht sicher, ob das überhaupt möglich ist, wenn ich Flask verwende.
Gibt es eine Möglichkeit, dies mit Flask oder einem Modul eines Drittanbieters zu erreichen?
Weitere Informationen
Die Daten werden über verschiedene Sockets und serielle Schnittstellen aktualisiert. Jede Schnittstelle wird in einem eigenen Thread ausgeführt und aktualisiert den gemeinsam genutzten Speicher. Beachten Sie, dass die Flask-/Webschnittstelle über schreibgeschützte Schreibvorgänge in den gemeinsam genutzten Speicher verfügt, die von den anderen Threads aktualisiert werden können.
Der gesamte Kundenpool sollte niemals 20 Personen überschreiten. Hierbei handelt es sich um eine Webschnittstelle zu einem Testsystem, mit der im Allgemeinen jeweils nur 1–5 Personen gleichzeitig verbunden sind.
Wie erhalten Sie Daten aus diesem externen Prozess?
– Russell Dias
12. Dezember 2011 um 6:01
Um zu vermeiden, dass die gesamte Seite aktualisiert wird, sollten Sie das sogenannte AJAX verwenden. Es sieht so aus, als wäre das einfach Im Kolben umsetzen.
Da dies regelmäßig geschehen soll, müssen Sie Ihre AJAX-Funktionen von a aus aufrufen Timer Funktion in Javascript.
Das bedeutet, dass Sie einfach das Javascript von der Flask-Seite in einen Timer-Aufruf einfügen.
So würde das Javascript ungefähr aussehen:
setInterval( //Periodically
function()
{
$.getJSON( //Get some values from the server
$SCRIPT_ROOT + '/get_values', // At this URL
{}, // With no extra parameters
function(data) // And when you get a response
{
$("#result").text(data.result); // Write the results into the
// #result element
});
},
500); // And do it every 500ms
Dadurch erhalte ich den Fehler: „feed.js:5 Uncaught ReferenceError: $SCRIPT_ROOT is not Defined“.
– Marshall
24. März 2016 um 14:05 Uhr
Ich denke, der einfachste Weg, dies zu tun, ist wahrscheinlich die Verwendung von Javascript, wie Sie in Ihrer Frage bereits vorgeschlagen haben. In diesem Fall würde Flask lediglich ein HTML-Dokument liefern, das Javascript-Code enthält, der vom Browser ausgeführt werden soll. Daher verstehe ich nicht, warum dies zu Problemen für Flask führen könnte. In diese Seiteich habe einige Beispiele gefunden, die unterschiedliche Kombinationen verwenden, z. B. die Verwendung eines Timers (was genau das zu sein scheint, wonach Sie suchen).
Danke für die Beispiele. Wenn ich gezwungen bin, die gesamte Seite zu aktualisieren, werden sie sehr nützlich sein. Haben Sie Ideen, wie Sie einen Teil der Seite aktualisieren können?
– Adam Lewis
12. Dezember 2011 um 6:13
Um nur einen Teil einer Seite neu zu laden, müssen Sie Ajax verwenden, um den Webserver nach der aktualisierten Version dieses Teils der Seite abzufragen (und Sie müssen dies auch auf der Serverseite implementieren). Der jquery Der Abschnitt in der Flask-Dokumentation sollte hilfreich sein, um damit zu beginnen.
– jcollado
12. Dezember 2011 um 6:25
Eine Möglichkeit, dies zu erreichen, ist die Verwendung von WebSockets in Flask Kolben-Sockelio. ich benutze APScheduler für den Hintergrundprozess im Beispiel, aber jeder Hintergrundprozess reicht aus. Dadurch wird alle 4 Sekunden ein Preis auf der Webseite aktualisiert:
from flask import Flask, render_template
from apscheduler.schedulers.background import BackgroundScheduler
from flask_socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app)
#defines the job
def job():
new_price = get_new_price();
#job emits on websocket
socketio.emit('price update',new_price, broadcast=True)
#schedule job
scheduler = BackgroundScheduler()
running_job = scheduler.add_job(job, 'interval', seconds=4, max_instances=1)
scheduler.start()
@app.route("https://stackoverflow.com/")
def index():
return render_template('index.html')
if __name__ == '__main__':
socketio.run(app, host="0.0.0.0")
Nein. Zumindest gibt es in Flask nichts, was dies einfacher machen würde als andere Lösungen. SO hat einiges anständiges Material zur Implementierung von Comet-Servern in Python.
Wie Sie bereits erwähnt haben, können Sie dort JavaScript verwenden, um den Server nach neuen Daten abzufragen. Dies kann jedoch für Ihren Server schwierig zu verwalten sein, wenn Sie viele Benutzer haben. Das Öffnen gleichzeitiger TCP-Verbindungen ist ziemlich teuer. Es bedeutet auch, dass Ihre Benutzeroberfläche möglicherweise etwas ruckelt, da die Dinge etwa jede Sekunde aktualisiert werden und nicht, wenn neue Daten auf den Server gelangen.
Vor diesem Hintergrund eignet sich Flask hervorragend für diese zweite Wahl, da es so einfach ist, Antwortfunktionen an einzelne URLs anzuhängen. Das Wichtigste, was Sie beachten sollten, ist, dass Sie Funktionen verwenden sollten, die die E/A stark blockieren. Lang laufende Funktionen belegen die gesamte Anwendung.
Nehmen wir an, Sie haben zwei Temperaturanzeigen und verwenden jQuery.
In einer JavaScript-Datei könnten Sie eine Funktion haben, die ein DOM-Element jede Minute mit der aktuellen Temperatur aktualisiert. Dieser Code soll Ihnen eine Vorstellung davon geben, was Sie in eine tatsächliche Implementierung einbauen können:
Wie erhalten Sie Daten aus diesem externen Prozess?
– Russell Dias
12. Dezember 2011 um 6:01