Сообщения асинхронного сервера с python flask - PullRequest
7 голосов
/ 06 февраля 2020

Я пытаюсь отправить серверные сообщения конечному пользователю, который зашел на наш flask веб-сайт.

Я провел некоторое исследование, и, похоже, лучшее решение - это использовать сокет- io.

Мои попытки, похоже, не работают, я должен также указать, что мои знания javascript очень основательны c.

Любая помощь / руководство будет высоко ценится.

См. мой код ниже:

python - app.py

from flask_socketio import SocketIO, emit
from flask import Flask, render_template, url_for, request
from time import sleep

app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
app.config['DEBUG'] = True

# turn the flask app into a socketio app
socketio = SocketIO(app, async_mode=None, logger=True, engineio_logger=True)

@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        if request.form['submit_button'] == 'Do Stuff':
            # server doing things....
            # the below method will make calls to emit socket messages
            # based on actions / outcome of actions.
            serverActions()
    return render_template('index.html')

@socketio.on('connect')
def connect():
    print('Client connected')

@socketio.on('display_message')
def displayMessage(message):
    socketio.emit('newmessage', {'message': message})
    socketio.sleep(2)

def serverActions():
    # get connection to DB
    message = "connecting to DB"
    # show message to user on flask page
    displayMessage(message)

    # test successful connection to DB
    message = "successfully connected to DB"
    displayMessage(message)

    # query the DB
    message = "querying the DB"
    displayMessage(message)

    # update DB
    message = "updating the DB"
    displayMessage(message)

    # etc......

if __name__ == '__main__':
    socketio.run(app)

HTML - шаблоны /index.html

<!DOCTYPE html>
<html>
<head>
    <script src="//code.jquery.com/jquery-3.3.1.min.js"></script>
    <script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
    <script src="static/js/application.js"></script>
</head>
<body>
  <form method="POST">
  <div>
    <div>
      <h1>Asynchronous Flask Communication</h1>
      <p>Messages generated by the Flask server should appear below, asynchronously.</p>
    </div>
  </div>

  <div>
      <p>Asynchronous page updates will appear here:</p>
      <div>
        <input type="submit" value="Do Stuff" name="submit_button">
      </div>
      <div>
        <h3>Server Messages:</h3>
        <div id="message">
        </div>
      </div>
  </div>

  </form>
</body>
</html>

javascript - статический / js / application. js

$(document).ready(function(){
    //connect to the socket server.
    var socket = io.connect('http://' + document.domain + ':' + location.port);

    //receive message details from server
    socket.on('display_message', function(msg) {
        console.log("Received message" + msg.message);
        message_string = '<p>' + msg.message + '</p>';
        $('#message').html(message_string);
    });

});

Ответы [ 3 ]

6 голосов
/ 09 февраля 2020

Вы emit события, которые вы прослушиваете с помощью обработчика событий on. Также я не думаю, что для вашего слушателя событий display_message имеет смысл находиться в конечной точке отдыха. Вот решение с pypubsub для удобства, так что вы можете легко подписаться на все события на сервере. Он может работать и без него, но здесь он

server.py

from flask_socketio import SocketIO, emit
from flask import Flask, render_template, url_for, request
from time import sleep
from pubsub import pub


app = Flask(__name__)
app.config['SECRET_KEY'] = 'secret'
app.config['DEBUG'] = True

# turn the flask app into a socketio app
socketio = SocketIO(app, async_mode=None, logger=True, engineio_logger=True)

def listener(arg1):
    print('Function listener1 received:')
    print('  arg1 =', arg1)
    socketio.emit('newmessage',{'message':arg1})


pub.subscribe(listener, 'rootTopic')

@app.route('/', methods=['GET', 'POST'])
def index():
    return render_template('index.html')

@app.route('/post', methods=['POST'])
def post():
    pub.sendMessage('rootTopic', arg1='post')

@socketio.on('connect')
def connect():
    pub.sendMessage('rootTopic', arg1='connected to socket')
    print('Client connected')



if __name__ == '__main__':
    socketio.run(app)

index. html

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title></title>
  </head>
  <body>
    <div id="message"></div>
    <button id="btn">CLICK</button>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.3.0/socket.io.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
    <script>
$(document).ready(function(){
    //connect to the socket server.
    var socket = io.connect('http://' + document.domain + ':' + location.port);
    $('#btn').on('click', function() {
      fetch('http://' + document.domain + ':' + location.port + '/post', {method:"POST"})
    })
    //receive message details from server
    socket.on('newmessage', function(msg) {
        console.log("Received message" + msg.message);
        message = '<p>' + msg.message + '</p>';

        $('#message').append(message);
    });

});
    </script>
  </body>
</html>
1 голос
/ 15 февраля 2020

Вот хитрость: отправлять сообщения группе. Таким образом, вы можете вызывать группу присоединения и добавлять всех в группу в журнале таким образом, что вы можете отправлять сообщения всем подключенным.

from flask import Flask
from flask_socketio import SocketIO, send, emit, join_room, leave_room

app = Flask('__name__')
socket = SocketIO(app, cors_allowed_origins="*", SameSite=None)


@socket.on('connect', namespace='/optional')
def connect():
    join_room('connected')

@app.route('/message')
def some_name():
    emit('message', 'your actual message', room='connected', namespace='/optional')

Теперь, когда вы нажмете на URL, он должен отправить сообщение всем подключенным. Помните, что пространство имен необязательно, но я рекомендую использовать его.

0 голосов
/ 14 февраля 2020

Проблема из приведенного вами примера заключается в том, что клиент, т.е. ваш JS в браузере, прослушивает событие display_message. Однако ваш сервер не излучает это событие, судя по всему. Каждый вызов displayMethod генерирует событие newmessage. Обновите ваш клиент, чтобы добавить прослушиватель событий для этого события.

    socket.on('newmessage', function(msg) {
        console.log("Received message" + msg.message);
        message_string = '<p>' + msg.message + '</p>';
        $('#message').html(message_string);
    });

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...