如何使用Flask-SQLAlchemy事件API广播到Flask-SocketIO?

7 投票
2 回答
1889 浏览
提问于 2025-04-18 08:19

我正在开发一个简单的多人游戏(想象一下扫雷),使用Flask作为后端API,AngularJS作为前端。我按照教程搭建了Angular和Flask的应用,并用Flask-Restless编写了一个RESTful API。

现在,我想在数据库中的游戏数据发生变化时,向所有客户端推送事件(这个变化是通过向Restless的某个接口发送POST请求来实现的)。我在考虑使用SqlAlchemy的event.listen API,来调用Flask-SocketIO的emit函数,将数据广播给客户端。这样做是否合适?这种方法有什么缺点吗?

2 个回答

1

这是你想要的代码的基本版本。我建议你从这里开始测试。你需要弄清楚“变化”具体指的是什么,这样你才能把合适的SqlAlchemy事件连接到你所做的变化类型上。

用户数据库在插入后监听事件

from sqlalchemy import event   
from app import socketio

def after_insert_listener(mapper, connection, target):
    socketio.emit('namespace response',{'data': data[0]},
                  namespace='/namespace')
    print(target.id_user)

event.listen(User, 'after_insert', after_insert_listener)

SocketIO

2

@CESCO的回复在所有计算都在同一个进程中时效果很好。你也可以使用这种语法(查看完整源代码):

@sa.models_committed.connect_via(app)
def on_models_committed(sender, changes):
    for obj, change in changes:
        print 'SQLALCHEMY - %s %s' % (change, obj)

如果你对订阅所有数据库更新感兴趣,可以继续阅读……




不过,如果你的数据库是从另一个进程更新的,这种方法就不行了。

models_committed只在提交来自同一个进程时有效(这不是数据库级别的通知,而是提交到数据库后由sqlalchemy发出的通知)

https://github.com/mitsuhiko/flask-sqlalchemy/issues/369#issuecomment-170272020

我写了一个小示例应用,展示如何使用Redis、ZeroMQ或socketIO_client与服务器进行实时更新的通信。这对任何想处理外部数据库访问的人可能会有帮助。

另外,你可以考虑订阅postgres事件:https://blog.andyet.com/2015/04/06/postgres-pubsub-with-json/

撰写回答