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
# ...
Related
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)})
I'm trying to build an API with flask_restful, but I don't know how to connect classes that inherit from Resource, with the actual app.
I have the following structure
page
├───api
│ └───__init__.py
│ └───resources.py
└───__init__.py
page/api/resources.py:
from flask_restful import Resource
from page import api
#api.resource("/hello-world")
class HelloWorld(Resource):
def get(self):
return {"hello": "World"}
page/init.py:
from flask import Flask
from flask_restful import Api
from page.config import Config1
api = Api()
def create_app(config_class=Config1):
app = Flask(__name__)
app.config.from_object(config_class)
api.init_app(app)
return app
run.py (outside of the page package):
from page import create_app
if __name__ == "__main__":
app = create_app()
app.run(debug=True)
test:
import requests
BASE = "http://127.0.0.1:5000/"
response = requests.get(BASE + "hello-world")
print(response.json())
Obviously, making a request to "/hello-world" doesn't work. How can I "make Flask aware" of the resources, so that I get a valid response.
Probably there is a much clever way of doing this but for me, the solution would be to remove the decorator #api.resource decorator at page/api/resources.py and make the following changes at page/init.py
from flask import Flask
from page.config import Config1
def create_app(config_class=Config1):
app = Flask(__name__)
app.config.from_object(config_class)
return app
I would also move the run.py inside the page folder and rename it to app.py according to Flask documentation. This app.py should have your routes so change it to something like this:
from page import create_app
from page.api.resources import HelloWorld
from flask_restfull import api
app = create_app()
api = Api(app)
api.add_resource(HelloWorld, '/hello-world')
And to run it just type flask run inside the page folder.
My code structure. I tried but kept getting error cannot import name 'caching'. I guess my method isn't correct as caching will not have app initiation when I import caching in external file.
xyz
-app.py
-run.py
-urls
-v2.py
-resource
-views.py
-external.py
run.py
from app import create_app
if __name__ == "__main__":
career_app = create_app()
career_app.run(host=HOST,
port=PORT,
debug=True)
app.py
from flask import Flask
from flask_caching import Cache
caching = Cache(config={'CACHE_TYPE': 'simple'})
def create_app():
"""Create web app."""
app = Flask(__name__)
configure_app(app)
caching.init_app(app)
setup_blueprints(app)
return app
external.py
from app import caching
v1.py
v2_api.add_resource(UserConfigView, '/user/config',
endpoint='user_config_view')
It is a simple factory app setup
ext.py
from flask_caching import Cache
cache = Cache()
app.py
def create_app():
app = Flask(__name__)
register_extensions(app)
...
def register_extensions(app):
cache.init_app(app, config=settings.params.CACHE_CONFIG)
I started by creating my Flask app the old school way: I had a Python package where I defined a variable called app, initialised it and then imported my code:
# -*- coding: utf-8 -*-
import os
from flask import Flask
app = Flask(__name__)
app.config.from_object('config')
app.secret_key = os.urandom(12)
from dashboard import forms, models, views
While adding unit tests to my project I found that I should use app factories so I created a factory:
# -*- coding: utf-8 -*-
import os
def create_app()
from flask import Flask
app = Flask(__name__)
app.config.from_object('config')
app.secret_key = os.urandom(12)
app = create_app()
from dashboard import forms, models, views
Except that with the factory my views are not loaded. Any route I call returns a 404. Without the factory everything works fine.
How can I diagnose what's going on?
Your create_app have to return app variable:
def create_app()
from flask import Flask
app = Flask(__name__)
app.config.from_object('config')
app.secret_key = os.urandom(12)
return app
Because default return is None
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!"