Was ist der beste Weg, eine erzwungene Seitenaktualisierung mit Flask zu implementieren?

Lesezeit: 5 Minuten

Benutzeravatar von Adam Lewis
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")

Dann ist die index.html Vorlage ist:

<!DOCTYPE HTML>
<html>
<head>
    <title>WebSockets Example</title>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
    <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
    <script type="text/javascript" charset="utf-8">
       $(document).ready(function(){

           var socket = io.connect('http://' + document.domain + ':' + location.port);

           socket.on('connect', function() {
               socket.emit('am up', {data: 'I\'m connected!'});
           });
           //listens to 'price update' message on socket
           socket.on('price update', function(msg) {
               $('#price_info').text(msg)
           });

       });
   </script>
</head>
<body>
  <div id="price_info"></div>
</body>
</html>

Tim McNamaras Benutzeravatar
Tim McNamara

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.

@app.route('/gauge/<int:gauge_id>')
def gauge_temp(gauge_id):
    temp = temp_from_db(gauge_id) #implement this yourself
    return dict(temp=temp, gauge_id=gauge_id)

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:

function updateTemp(gauge_id, selector) {
  $.getJSON('/gauge/' + gauge_id, function(data){
    $(selector).text = response.temp;
  })
}

setInterval('updateTemp(1, "#gauge-1")', 1000 * 60);
setInterval('updateTemp(2, "#gauge-2")', 1000 * 60);

1452380cookie-checkWas ist der beste Weg, eine erzwungene Seitenaktualisierung mit Flask zu implementieren?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy