Introducing flask_socketio to work with a simple already made flask application - python

I'm new to both Flask and flask-socketio.
I first made the tutorial app from Flask official docs.
And I follow this to make a simple chat app using flask-socketio.
What I need is the authentication system from Flask tutorial and the simple chat feature from the SocketIO tutorial.
The Flask tutorial runs the Flask app inside the create_app method in __init__.py.
__init__.py:
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
# ...
return app
The SocketiIO tutorial have only a main.py file that runs the SocketIO application.
main.py:
app = Flask(__name__)
app.config['SECRET_KEY'] = 'vnkdjnfjknfl1232#'
socketio = SocketIO(app)
#app.route('/')
def sessions():
return render_template('session.html')
# ...
if __name__ == '__main__':
socketio.run(app, debug=True)
I've been read a lot of questions about integrating flask-socketio with already made Flask application, but all of them try to integrate using a main.py file that you can put socketio.run() method to run inside the if __name__.
Is it possible to run both http server with socket server in the same app initializing the app from create_app method?

For people that reach this question, the creator of the package teaches how to deal with this issue here.
socketio = SocketIO()
def create_app(test_config=None):
# create and configure the app
app = Flask(__name__, instance_relative_config=True)
app.config.from_mapping(
SECRET_KEY='dev',
DATABASE=os.path.join(app.instance_path, 'flaskr.sqlite'),
)
# ...
socketio.init_app(app)
return app
It's just a matter of creating a global SocketIO object and starting after in creat_app.

Related

How can i use two waitress server for django app

I want to have 2 waitress servers for hosting django web application.One for serving statics and media files of django app and other for django on different ports.
I tried some thing like this and hit localhost:6003 in browser,but it is serving only static web page at 6003 and is not interacting with app running at 9090. what am i missing?
I have successfully deployed this app usig nginx-waitress architecture.But I want to deploy using waitress -waitress architecture.
app.py
from flask import Flask
from flask_cors import CORS, cross_origin
app = Flask(__name__,)
CORS(app)
main.py
from flask import Blueprint, send_from_directory
from waitress import serve
from app import app
#app.route('/stat/<path:filename>')
def static_file(filename):
return send_from_directory("D:/static/",filename)
#app.route('/med/<path:filename>')
def media_file(filename):
return send_from_directory("D:/media/",filename)
serve(app, host='localhost', port=6003)
runserver.py
from waitress import serve
from sarus_project.wsgi import application
if __name__ == '__main__':
serve(application, host = 'localhost', port='9090')

Flask + SocketIO start/stop subapp with DispatcherMiddleware

I have an Flask server with SocketIO and DispatcherMiddleware now i want to start/stop an subapp on runtime if i call the routes (start/stop) with the subapp name as an url argument than the app should start/stop but not the whole server only the subapp.
Here are my setup (init app).
init.py
from flask import Flask
from flask_socketio import SocketIO
from werkzeug.middleware.dispatcher import DispatcherMiddleware
from app1 import app1
from app2 import app2
# Setup the main app.
app = Flask(__name__)
# Stop the Blueprint app.
#app.route('/stop<app>', methods=['GET'])
def stop_app(app):
pass
# Start the Blueprint app.
#app.route('/start<app>', methods=['GET'])
def start_app(app):
pass
# Create the dispatcher with all Blueprint apps.
app.wsgi_app = DispatcherMiddleware(app, {"/app1": app1, "/app2": app2})
# Create the socketio app.
socketio = SocketIO(app, async_mode="threading")
# Start the app.
socketio.run(app, "localhost", 80)
Here are the subapps.
app1.py
from flask import Flask
# Setup the Blueprint app.
app1 = Flask(__name__)
# INFO Create Main Blueprints.
hello = Blueprint('hello', __name__)
#hello.route('/hello', methods=['GET'])
def hello_blp():
print("hello")
# Register all Blueprints.
app1.register_blueprint(hello)
app2.py
from flask import Flask
# Setup the Blueprint app.
app2 = Flask(__name__)
# INFO Create Main Blueprints.
world = Blueprint('world', __name__)
#world.route('/world', methods=['GET'])
def world_blp():
print("world")
# Register all Blueprints.
app2.register_blueprint(world)
Thanks for any help or idea how i can make this.
I have found an solution.
Here are the codes.
stop
# Stop the Blueprint app.
#app.route('/stop<app_name>', methods=['GET'])
def stop_app(app_name):
del app.wsgi_app.wsgi_app.mounts[f"/{app_name}"]
start
# Start the Blueprint app.
#app.route('/start<app_name>', methods=['GET'])
def start_app(app_name):
app.wsgi_app.wsgi_app.mounts.update({f"/{app_name}": create_app(app_name)})

flask server won't run if I named my application factory function other than "create_app"

My server will run if I name application factory function as create_app like this:
def create_app():
app = Flask(__name__)
#app.route('/')
def hello():
return 'Hello, World!'
return app
but naming it other than create_app, will throw an error Failed to find Flask application or factory
def foo_app():
app = Flask(__name__)
#app.route('/')
def hello():
return 'Hello, World!'
return app
changing the case will also throw the same error, like this:
def Create_app():
app = Flask(__name__)
#app.route('/')
def hello():
return 'Hello, World!'
return app
Is this behavior is normal? or is there something wrong in my setup?
this is my project layout:
...\projects\mainfoo
|--packagefoo
| |--__init__.py
|--venvfiles
in the cmd,
...\projects\mainfoo>set FLASK_APP=packagefoo
...\projects\mainfoo>set FLASK_ENV=development
...\projects\mainfoo>flask run
I just follow this tutorial Project Layout & Application setup
From the flask documentation
$ export FLASK_APP=hello
$ flask run
While FLASK_APP supports a variety of options for specifying your
application, most use cases should be simple. Here are the typical
values:
(nothing)
The name “app” or “wsgi” is imported (as a “.py” file, or
package), automatically detecting an app (app or application) or
factory (create_app or make_app).
FLASK_APP=hello
The given name is imported, automatically detecting an
app (app or application) or factory (create_app or make_app).
You cannot customize this behavior, as its a specification in flask to follow.

Integrate multiple Dash apps into Flask

I`m trying to integrate multiple Dash apps into a Flask application, but not able to do so.
I was able to integrate one Dash app into Flask, using the following structure:
dashboard1.py
def create_dashboard(server):
dash_app = dash.Dash(server=server,
routes_pathname_prefix='/dash1/',
external_stylesheets=[dbc.themes.BOOTSTRAP],
)
....
return dash_app.server
init.py
from flask import Flask
from flask_assets import Environment
def create_app():
"""Construct core Flask application with embedded Dash app."""
f_app = Flask(__name__, instance_relative_config=False)
f_app.config.from_object('config.Config')
assets = Environment()
assets.init_app(f_app)
with f_app.app_context():
# Import parts of our core Flask app
from . import routes
from .assets import compile_static_assets
# Import Dash application
from .plotlydash.dashboard import create_dashboard
app = create_dashboard(f_app)
# Compile static assets
compile_static_assets(assets)
return app
routes.py
from flask import render_template, redirect
from flask import current_app as app
#app.route('/dash1')
def dash1():
return render_template('dash1.html', app_data=app_data)
app.py
from application import create_app
app= create_app()
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True)
Everything is working fine with the first Dash app. I want to create another menu/tab in the application and integrate a second dash app. How could I do this? I have tried the following but it has not resulted successful. Only the link of the first app works.
dashboard2.py
def create_dashboard2(server):
dash_app = dash.Dash(server=server,
routes_pathname_prefix='/dash2/',
external_stylesheets=[dbc.themes.BOOTSTRAP],
)
....
return dash_app.server
init.py
from flask import Flask
from flask_assets import Environment
def create_app():
"""Construct core Flask application with embedded Dash app."""
f_app = Flask(__name__, instance_relative_config=False)
f_app.config.from_object('config.Config')
assets = Environment()
assets.init_app(f_app)
with f_app.app_context():
# Import parts of our core Flask app
from . import routes
from .assets import compile_static_assets
# Import Dash application
from .plotlydash.dashboard1 import create_dashboard
from .plotlydash.dashboard2 import create_dashboard2
app = create_dashboard(f_app)
app2 = create_dashboard2(f_app)
# Compile static assets
compile_static_assets(assets)
return app, app2
routes.py
from flask import render_template, redirect
from flask import current_app as app
#app.route('/dash1')
def dash1():
return render_template('dash1.html', app_data=app_data)
#app.route('/dash2')
def dash2():
return render_template('dash2.html', app_data=app_data)
app.py
from application import create_app
app, app2= create_app()
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True)
app2.run(host='0.0.0.0', debug=True)
Could you please help me with some pointer/indications of what I might be doing wrong?
To answer #mLstudent33's question about callbacks initialization in the comments - there is a good blog post about it - https://hackersandslackers.com/plotly-dash-with-flask.
I followed their instructions and this worked for me:
For example, dashboard1.py:
def create_dashboard(server):
dash_app = dash.Dash(
server=server,
routes_pathname_prefix='/dash1/',
external_stylesheets=[dbc.themes.BOOTSTRAP],
)
dash_app.layout = html.Div([
# ... Layout stuff
])
# Initialize callbacks after our app is loaded
# Pass dash_app as a parameter
init_callbacks(dash_app)
return dash_app.server
def init_callbacks(dash_app):
#dash_app.callback(
# Callback input/output
....
)
def update_graph(rows):
# Callback logic
# ...

NameError: name 'app' is not defined with Flask

I have the following structure in my project
\ myapp
\ app
__init__.py
views.py
run.py
And the following code:
run.py
from app import create_app
if __name__ == '__main__':
app = create_app()
app.run(debug=True, host='0.0.0.0', port=5001)
views.py
#app.route("/")
def index():
return "Hello World!"
_init_.py
from flask import Flask
def create_app():
app = Flask(__name__)
from app import views
return app
I'm trying to use the factory design pattern to create my app objects with different config files each time, and with a subdomain dispatcher be able to create and route different objects depending on the subdomain on the user request.
I'm following the Flask documentation where they talk about, all of this:
Application Context
Applitation Factories
Application with Blueprints
Application Dispatching
But I couldn't make it work, it seems that with my actual project structure there are no way to pass throw the app object to my views.py and it throw and NameError
NameError: name 'app' is not defined
After do what Miguel suggest (use the Blueprint) everything works, that's the final code, working:
_init.py_
...
def create_app(cfg=None):
app = Flask(__name__)
from api.views import api
app.register_blueprint(api)
return app
views.py
from flask import current_app, Blueprint, jsonify
api = Blueprint('api', __name__)
#api.route("/")
def index():
# We can use "current_app" to have access to our "app" object
return "Hello World!"

Categories

Resources