miguelgrinberg/Flask-SocketIO-Chat

Best way to embed Flask-SocketIO-Chat into another app?

scheung38 opened this issue · 23 comments

Say we have another standalone running Flask app, how to embed and launch Flask-SocketIO-Chat when one of its navigational tabs is clicked:

@app.route(/chat):
def chat():
    return render_template(launch Flask-SocketIO-Chat here)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=8080, debug=True)

Since Flask-SocketIO-Chat is already launched from within chat.py?

You can choose to merge the chat functionality into your application, or keep it separate.

If you merge it, then you will have a chat route that serves the chat template that contains the client-side javascript for the page.

If you keep it separate, you need to run the application and the chat separately (on separate ports), and the application will have to be configured to know what URL to use to embed the chat.

Thanks, is it a lot of work for both options? Or better and easier to maintain separate apps and do a lot of importing? Not sure where to start in terms of the configuration needed.

I would combine everything in a single application. Just put the chat portion under a /chat route, so that it does not collide with the application routes.

Alternatively merging your Flask-SocketIO-Chat as one of the tabs in your microblog? So after login and authenticated, 'Chat' will be next to the Logout or other available tabs.

  1. Refactored package names in Flask-SocketIO-Chat to chat-app
  2. Refactored package names in microblog to main-app before copying all folders from Flask-SocketIO-Chat into microblog to avoid package name clashes.
  3. Then changed run.py in microblog:
from gevent import monkey
monkey.patch_all()
from app_main import create_app, socketio

app = create_app(True)
# app.run(debug=True)
if __name__ == '__main__':
    socketio.run(app)

and now the microblog/app_main/ __init__.py:

def create_app(debug=False):
    global app, db, lm, oid, mail, babel
    app = Flask(__name__)
    app.config.from_object('config')
    db = SQLAlchemy(app)
    lm = LoginManager()
    lm.init_app(app)
    lm.login_view = 'login'
    lm.login_message = lazy_gettext('Please log in to access this page.')
    oid = OpenID(app, os.path.join(basedir, 'tmp'))
    mail = Mail(app)
    babel = Babel(app)

    app.debug = debug
    app.config['SECRET_KEY'] = 'gjr39dkjn344_!67#'
    from app_chat.main import main as main_blueprint
    app.register_blueprint(main_blueprint)

    socketio.init_app(app)
    return app

But app is still not global? Because I get:

app.json_encoder = CustomJSONEncoder
NameError: global name 'app' is not defined

Could this be related this this question:
http://stackoverflow.com/questions/21028254/nameerror-name-app-is-not-defined-with-flask

I don't see where you have the reference to app.json_encoder, so I can't really tell you what the problem is.

Also the global app is suspicious. If you are using the app factory pattern then you do not need to make app a global variable.

In microblog(app - > app_main)-> __init__.py, but does defining global app inside create_app already makes it global?

def create_app(debug=False):
    global app, db, lm, oid, mail, babel
    app = Flask(__name__)
    app.config.from_object('config')
    db = SQLAlchemy(app)
    lm = LoginManager()
    lm.init_app(app)
    lm.login_view = 'login'
    lm.login_message = lazy_gettext('Please log in to access this page.')
    oid = OpenID(app, os.path.join(basedir, 'tmp'))
    mail = Mail(app)
    babel = Babel(app)

    app.debug = debug
    app.config['SECRET_KEY'] = 'gjr39dkjn344_!67#'
    from app_chat.main import main as main_blueprint
    app.register_blueprint(main_blueprint)

    socketio.init_app(app)
    return app

class CustomJSONEncoder(JSONEncoder):
    """This class adds support for lazy translation texts to Flask's
    JSON encoder. This is necessary when flashing translated texts."""
    def default(self, obj):
        from speaklater import is_lazy_string
        if is_lazy_string(obj):
            try:
                return unicode(obj)  # python 2
            except NameError:
                return str(obj)  # python 3
        return super(CustomJSONEncoder, self).default(obj)

app.json_encoder = CustomJSONEncoder

Yeah, okay. You can't access app in the global scope if you are working with an app factory function. That needs to go in the factory function.

Sorry the factory function is located in?

Doesn't matter where you put the factory function. It can go in the __init__.py file, or in a different module inside the application package.

It seems to me you are trying to convert microblog to use an app factory function, but you did not go all the way with the conversion. Any references to app as a global variable need to go, there is no app global when you structure your application in this form.

Sorry, I meant how do you make a factory function as opposed to the file location.

This repository has a factory function in this file, that should be a good example.

If you want to see one a bit more complex, the one in my Flasky repository is a good one to study.

Thanks I thought it was blueprint related.

I'm also looking to implement this under a larger web application. Any recommendations for storing a history of the messages?

@alexwaters It depends on your needs. Storing them in memory, a file or a database should all work.

hello Miguelgrinberg

How can i work with Flask socketio blueprints to pull data from Ibm watson

@KunleMichaels not sure what you are asking. What do you mean by "flask socketio blueprints"?
Presumably Watson has some API mechanism for clients to get data? I don't see what Flask-SocketIO has to do with it.

Thanks for the reply Miguel, I'm not so good with the terms but I will try to be as clear as possible

I'm building a bot that carries out financial services based on requests from users I'm working with IBM dashdb, how can I use a flask framework without sqlalchemy and sqlite. Since IBM dashdb doesn't support sqlalchemy

Flask does not require sqlalchemy, you can use any database that you like. For dashdb, you can use https://pypi.python.org/pypi/ibmdbpy.

Thanks a whole lot @miguelgrinberg

This issue will be automatically closed due to being inactive for more than six months. Seeing that I haven't responded to your last comment, it is quite possible that I have dropped the ball on this issue and I apologize about that. If that is the case, do not take the closing of the issue personally as it is an automated process doing it, just reopen it and I'll get back to you.