Hi @miguelgrinberg hope you're doing great, Paul here! (from the geoalchemy issue on flask-migrate a few weeks ago, big fan!). I am having some issues with getting my socketio handlers to work. I noticed a common cause that you've addressed in the past is "not importing them into your blueprint" so i have made sure to do that. My project structure is a lot like the one in this chat example, only i have more blueprints inside of a parent folder, its like this:
projectfolder/
- core/
| - __init__.py
| - bookings (blueprint)/
| - __init__.py
| - events.py
| - views.py
| - other blueprint
| - other blueprint
- wsgi.py
Here's what I have in bookings blueprint init.py
file:
# flake8: noqa
from flask import Blueprint
bookings = Blueprint(
"bookings", __name__, url_prefix="/bookings",
template_folder='templates', static_folder='static'
)
from . import views, events
I have imported the events as you can see here.
In the bookings events.py
file i have added the following handlers:
from core import socketio
from flask_socketio import send, emit
from flask import request
from core import db
from models.utils import Socket
from tasks.push_booking_to_queue import pbq
from extensions import redis_
import pygeohash as pgh
@socketio.on('location_update', namespace='/artisan')
def update_location(data):
# update artisan location on redis
redis_.geoadd(
name="artisan_pos",
values=(data['lat'], data['lon'], data['artisan_id'])
)
# option one
@socketio.on('order_updates')
def get_updates(data):
# add client to special room
room = request.sid
# continually query celery for updates
while True:
task = pbq.AsyncResult(data['task_id'])
if task.state == 'SUCCESS':
result = task.info.get('match_profile')
send(result, to=room)
break
@socketio.on('accept_offer')
def offer(data):
room = request.sid
# notify client of update
# order =
emit('message', data, to=room)
print(data)
@socketio.on('connect')
def connect():
emit('welcome', 'welcome!', broadcast=True)
print('someone connected')
Here i anticipate that the connection handler at least works but not any of the handlers are being triggered.
Here's the app factory in core/__init__.py
from flask import Flask
from config import config_options, DevConfig
from flask_sqlalchemy import SQLAlchemy
from flask_marshmallow import Marshmallow
from flask_migrate import Migrate
from flask_socketio import SocketIO
from celery import Celery
from flask_cors import CORS
# instantiate extensions
db, ma = SQLAlchemy(), Marshmallow()
socketio = SocketIO()
migrate = Migrate(include_schemas=True)
celery = Celery(__name__, broker=DevConfig.CELERY_BROKER_URL)
cors = CORS()
# app factory
def create_app(config_name):
app = Flask(__name__)
# configure application
app.config.from_object(config_options[config_name])
# link extensions to app instance
db.init_app(app)
ma.init_app(app)
migrate.init_app(app, db)
celery.conf.update(app.config)
cors.init_app(app)
# register blueprints
from .bookings import bookings
from .payments import payments
from .ratings import ratings
from .security import security
from .user import user
app.register_blueprint(bookings)
app.register_blueprint(payments)
app.register_blueprint(ratings)
app.register_blueprint(security)
app.register_blueprint(user, url_prefix='/user')
# socketio.init_app(app, async_mode="eventlet", engineio_logger=True)
socketio.init_app(app)
return app
And finally the wsgi.py
file which runs the application:
# flake8: noqa
from json import load
from core import create_app, socketio
from dotenv import load_dotenv
from models.user_models import *
from models.base import *
from models.documents import *
from models.address import *
from models.bookings import *
from models.ratings import *
from models.location import *
from models.payments import *
from models.utils import *
import os
load_dotenv()
app = create_app(os.getenv('FLASK_CONFIG') or 'default')
@app.shell_context_processor
def make_shell_context():
return dict(app=app, role=Role)
if __name__ == "__main__":
# socket.run(app, host="0.0.0.0", port=5000)
socketio.run(app)
I don't know if this is a consequence of putting all my blueprints in a package, because i see that your chat app example only has one blueprint which is on the same level as the chat.py
that runs the application. Hopefully this is descriptive enough, i look forward to hearing from you, thank you!.