dash within flask app from external folder - python

I have seen many discussions about running dash within flask but cannot make my own case to work.
I have ~4 pages in dash and now I would like to run them with flask (using an index file works just fine).
In this thread there is some code to tackle the issue
from dash import Dash,html
from werkzeug.middleware.dispatcher import DispatcherMiddleware
import flask
from werkzeug.serving import run_simple
import dash_html_components as html
server = flask.Flask(__name__)
dash_app1 = Dash(__name__, server=server, url_base_pathname='/dashboard')
dash_app2 = Dash(__name__, server=server, url_base_pathname='/reports')
dash_app1.layout = html.Div([html.H1('Hi there, I am app1 for dashboards')])
dash_app2.layout = html.Div([html.H1('Hi there, I am app2 for reports')])
#server.route('/')
#server.route('/hello')
def hello():
return 'hello world!'
#server.route('/dashboard/')
def render_dashboard():
return flask.redirect('/dash1')
#server.route('/reports/')
def render_reports():
return flask.redirect('/dash2')
app = DispatcherMiddleware(server, {
'/dash1': dash_app1.server,
'/dash2': dash_app2.server
})
run_simple('0.0.0.0', 8080, app, use_reloader=True, use_debugger=True)
And works, however when I am trying to import my own app it doesn't due to 404 not found. I can replicate the error easily by doing having the two dash apps in separate files like this
dummy/app1.py
from dash import Dash,html
import flask
server = flask.Flask(__name__)
dash_app1 = Dash(__name__, server=server, url_base_pathname='/dashboard/')
dash_app1.layout = html.Div([html.H1('Hi there, I am app1 for dashboards')])
dummy/app2.py
from dash import Dash,html
import flask
server = flask.Flask(__name__)
dash_app2 = Dash(__name__, server=server, url_base_pathname='/reports/')
dash_app2.layout = html.Div([html.H1('Hi there, I am app2 for reports')])
wsgi.py
from werkzeug.middleware.dispatcher import DispatcherMiddleware
import flask
from werkzeug.serving import run_simple
from dummy.app1 import dash_app1
from dummy.app2 import dash_app2
server = flask.Flask(__name__)
#server.route('/')
#server.route('/hello')
def hello():
return 'hello world!'
#server.route('/dashboard/')
def render_dashboard():
return flask.redirect('/dash1/')
#server.route('/reports/')
def render_reports():
return flask.redirect('/dash2/')
app = DispatcherMiddleware(server, {
'/dash1/': dash_app1.server,
'/dash2/': dash_app2.server
})
run_simple('0.0.0.0', 8080, app, use_reloader=True, use_debugger=True)
I tried moving the server.route within each dash app but without success. what am I missing?

Related

Flask 404 error when initializing a connection with a react applicaiont

import os, re
from flask import Flask, send_from_directory, json,request
from flask_socketio import SocketIO
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
import random
app = Flask(__name__, static_folder='./build/static')
# Point SQLAlchemy to your Heroku database
uri = os.getenv("DATABASE_URL") # or other relevant config var
if uri and uri.startswith("postgres://"):
uri = uri.replace("postgres://", "postgresql://", 1)
app.config['SQLALCHEMY_DATABASE_URI'] = uri
# Gets rid of a warning
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
import models
cors = CORS(app, resources={r"/*": {"origins": "*"}})
socketio = SocketIO(
app,
cors_allowed_origins="*",
json=json,
manage_session=False
)
#app.route('/', defaults={"filename": "index.html"})
#app.route('/<path:filename>')
def index(filename):
return send_from_directory('./build', filename)
# When a client connects from this Socket connection, this function is run
#socketio.on('connect')
def on_connect():
print('User connected!')
# When a client disconnects from this Socket connection, this function is run
#socketio.on('disconnect')
def on_disconnect():
print('User disconnected!')
#socketio.on('index')
def on_index():
all_students = db.Students.query.all()
random1 = random.randint(0,models.Students.query().count())
random2 = random.randint(0,models.Students.query().count())
total_table = []
for student in all_students:
total_table.append(student)
firstStudent = []
secondStudent = []
while(random2 == random1):
random2 = random.randint(0,models.Students.query().count())
firstStudent.append(total_table[random1])
secondStudent.append(total_table[random2])
twoStudents = [firstStudent,secondStudent]
socketio.emit('students', {twoStudents:twoStudents})
# Note we need to add this line so we can import app in the python shell
if __name__ == "__main__":
# Note that we don't call app.run anymore. We call socketio.run with app arg
socketio.run(
app,
)
The react end of the application launches fine with no errors, and the database has no issues. I've used this skeleton for the base of a bunch of other projects and i've never had any issues. But for some reason i'm stuck at a brick wall setting this up. I know the issue is within the #app.route('/') part of the code. i've tried hard coding the html file into the url path, but that just causes other errors like missing 1 required positional argument: 'filename' flask. Any help is greatly appreciated
I tested your configuration and it doesn't give me any errors. Nevertheless I offer you an alternative solution.
You can provide the entire react build folder as a static folder. You can then deliver the "index.html" as a single file in the root route. The prerequisite is that the prefix for the static url path is empty.
# ...
app = Flask(__name__,
static_url_path='',
static_folder='./build'
)
# ...
#app.route('/')
def index():
return app.send_static_file('index.html')
# ...

How do I implement proper Flask server that contains Server-Sent-Event API?

[Flask SSE API doesn't work on production]
Hi, i'm facing an issue in my flask application where I have multiple regular APIs and 1 HTTP API that sends SSE to my React app. In my local development env, the app works just fine as expected. However, when I deployed it to CPanel shared hosting, I noticed that the the React app makes proper request of Content-Type text/event-stream, but received text/html response header from the API after 2 minute timeout. Is there anything wrong with how I implemented the server?
main.py
from myapplication import create_app
from flask import stream_with_context
from gevent import monkey; monkey.patch_all()
from gevent.pywsgi import WSGIServer
app = create_app()
if __name__ == '__main__':
http_server = WSGIServer(("localhost", 5000), app)
http_server.serve_forever()
myapplication/init.py
from flask import Flask
from flask_cors import CORS
from flask_sqlalchemy import SQLAlchemy
from os import path, environ
from dotenv import load_dotenv
db = SQLAlchemy()
DATABASE_NAME = 'database.db'
load_dotenv()
def get_database_uri():
host = environ['DB_HOST']
port = environ['DB_PORT']
name = environ['DB_NAME']
username = environ['DB_USER']
password = environ['DB_PASS']
return f'postgresql+psycopg2://{username}:{password}#{host}:{port}/{name}'
def create_database(app):
if not path.exists('myapplication/' + DATABASE_NAME):
db.create_all(app=app)
print('Database created.')
def create_app():
app = Flask(__name__)
CORS(app)
cors = CORS(app, resource = {
r"/*": {
"origins": "*"
}
})
app.config['SECRET_KEY'] = environ['SECRET_KEY']
app.config['SQLALCHEMY_DATABASE_URI'] = get_database_uri()
db.init_app(app)
from .gallery import gallery
from .document import document
from .timer import timer
from .member import member
app.register_blueprint(gallery, url_prefix='/gallery')
app.register_blueprint(document, url_prefix='/document')
app.register_blueprint(timer, url_prefix='/timer')
app.register_blueprint(member, url_prefix='/member')
from .models import Member, Gallery, Document, Timer
create_database(app)
return app
timer.py (SSE api)
global_count = '60'
global_refresh_count = '0'
#timer.route('/stream')
def get_current_stream():
def send_event():
while True:
event_payload = '{"count": "%s", "refreshCount": "%s"}'%(global_count, global_refresh_count)
data_message = f'data: {str(event_payload)}\n\n'
yield data_message
time.sleep(1)
return Response(send_event(), mimetype='text/event-stream')
Local development response:
dev response
Local development eventstream response:
dev event stream response
Production response:
prod response
CPanel python app setup:
Application startup file: passenger_wsgi.py
Application Entry point: application
passenger_wsgi.py
import imp
import os
import sys
sys.path.insert(0, os.path.dirname(__file__))
wsgi = imp.load_source('wsgi', 'main.py')
application = wsgi.app
Please kindly help guide me folks, much appreciated!
you have to set certain headers like below
resp = Response(
send_event(),
mimetype='text/event-stream'
)
resp.headers['X-Accel-Buffering'] = 'no'
resp.headers['Cache-Control'] = 'no-cache'
return resp
and configure setting throughout your service
for example in case of nginx:
location '/' {
proxy_buffering off;
proxy_cache off;
proxy_read_timeout 12h;
...
proxy_pass {your_route};
}
in case of gunicorn:
set timeout param to 0 when you execute it.
/{path_to}/gunicorn --workers {num_workers} --timeout 0 --bind {path} -m 007 {module}:{app_name}

How can I run a Flask app hosted on a2hosting?

I have just setup my first Flask project hosted on a server (a2hosting). Now, I want to run on the web application my python script (calculating a few things and then redirects to other url).
But I am not sure how do I set it up on my app server in a2hosting?
# A very simple Flask Hello World app for you to get started with...
from flask import Flask ,redirect
app = Flask(__name__)
#app.route('/set/<hana>')
def hello_world(hana):
import googlemaps
name = hana
return redirect('http://mycamp.co.il/yesh/'+name , code=302)
#app.route('/hello')
def hiii():
import pymongo
def insert(myreq):
dd={
"hihi":"yes1yes"
}
myreq.insert_one(dd)
return True
client = pymongo.MongoClient("mongodb://DETAILES.#routeplan-shard-00-00-d416l.gcp.mongodb.net:27017,routeplan-shard-00-01-d416l.gcp.mongodb.net:27017,routeplan-shard-00-02-d416l.gcp.mongodb.net:27017/test?ssl=true&replicaSet=routeplan-shard-0&authSource=admin&retryWrites=true")
mydb = client['router']
myplan = mydb['planner']
mydis = mydb['distance']
myopt = mydb['optimal']
myreq = mydb['request']
myus = mydb['user']
q=insert(myreq)
return 'helo world %s' + q
if __name__ == '__main__':
app.run(debug = True)

dash app in iframe more secure [duplicate]

I have an existing Flask app, and I want to have a route to another app. More concretely, the second app is a Plotly Dash app. How can I run my Dash app within my existing Flask app?
#app.route('/plotly_dashboard')
def render_dashboard():
# go to dash app
I also tried adding a route to the Dash instance, since it's a Flask app, but I get the error:
AttributeError: 'Dash' object has no attribute 'route'
From the docs:
The underlying Flask app is available at app.server.
import dash
app = dash.Dash(__name__)
server = app.server
You can also pass your own Flask app instance into Dash:
import flask
server = flask.Flask(__name__)
app = dash.Dash(__name__, server=server)
Now that you have the Flask instance, you can add whatever routes and other functionality you need.
#server.route('/hello')
def hello():
return 'Hello, World!'
To the more general question "how can I serve two Flask instances next to each other", assuming you don't end up using one instance as in the above Dash answer, you would use DispatcherMiddleware to mount both applications.
dash_app = Dash(__name__)
flask_app = Flask(__name__)
application = DispatcherMiddleware(flask_app, {'/dash': dash_app.server})
Set url_base_pathname in your Dash instance.
app_flask = flask.Flask(__name__)
app_dash = dash.Dash(__name__, server=app_flask, url_base_pathname='/pathname')
Now you can redirect to your Plotly Dashboard app under any Flask routes you want.
#app_flask.route('/plotly_dashboard')
def render_dashboard():
return flask.redirect('/pathname')
Ok for those who are lazy enough like me, here is the code
from dash import Dash
from werkzeug.wsgi import DispatcherMiddleware
import flask
from werkzeug.serving import run_simple
import dash_html_components as html
server = flask.Flask(__name__)
dash_app1 = Dash(__name__, server = server, url_base_pathname='/dashboard' )
dash_app2 = Dash(__name__, server = server, url_base_pathname='/reports')
dash_app1.layout = html.Div([html.H1('Hi there, I am app1 for dashboards')])
dash_app2.layout = html.Div([html.H1('Hi there, I am app2 for reports')])
#server.route('/')
#server.route('/hello')
def hello():
return 'hello world!'
#server.route('/dashboard')
def render_dashboard():
return flask.redirect('/dash1')
#server.route('/reports')
def render_reports():
return flask.redirect('/dash2')
app = DispatcherMiddleware(server, {
'/dash1': dash_app1.server,
'/dash2': dash_app2.server
})
run_simple('0.0.0.0', 8080, app, use_reloader=True, use_debugger=True)
#here are full codee
from dash import Dash
import flask
from dash import html
server = flask.Flask(__name__)
app = Dash(__name__, server=server, url_base_pathname='/ATM_Data_Anlaysis/')
app.layout = html.Div([html.H1('This Is head',style={'textAlign':'center'})])
#server.route("/dash")
def MyDashApp():
return app.index()
if __name__ == '__main__':
app.run_server(debug=True)
To solve this issue, here is what I did and was successful. This should be documented in official DASH documentation
####################################
import dash_core_components as dcc
import dash_html_components as html
from dash import Dash
from dash.dependencies import Input, State, Output
from flask import Flask, flash, redirect, render_template, request, session, abort, url_for, json, make_response
url_router=''
#application.route("/view_tables", methods=['GET','POST'])
def view_tabales:
# Logic for displaying dashboard using Dash
server.layout = html.Div(
children=[
#division for graph 1
html.Div([html.H1(children='Capital Charge'),],className='text-center'),
html.Div([html.Div([html.H3(children='''Correlation for assets'''),],className='text-primary'),
# define the graph
dcc.Graph(
id='Delta-graph',
figure={
'data': [
{'x': df_delta['Correlation_Level'],
'y': df_delta['Capital_Charge'],
'type': 'bar',
'name': 'Delta',
#'domain': {'x': [0, .48],'y': [0, .49]},
}
],
# sizes the graph
'layout': {
'title': 'Delta','margin': {'l': 10, 'r': 0, 't': 30, 'b': 10},
"height":300,
}
}
)],className='col-md-4'),
url_router = 'Dash(__name__,server=application, url_base_pathname="/dash")'
Then you can control which dashboard it is headed from inside flask
if url_router !='':
server = url_router
server.layout = html.Div(children = [html.H1(children = ' MEP dashboard - error 404')])
# run the app.
if __name__ == "__main__":
# Setting debug to True enables debug output. This line should be
# removed before deploying a production app.
server.secret_key = os.urandom(12)
server.run_server(debug=True,port=5000)
you can create different functions with different graphs between the Flask code and keep calling the code in dash

Deploying Flask_restplus Api build over Flask App using uwsgi.py on nginx server

All
I have a flask_rest plus api over flask app in python. I want to deploy the same using the uwsgi format on nginx server. I searched for quite a long but didn't found the write solution.Any leads would be helpful..
Thanks in advance.
Below is the code snippet
import datetime
from fileinput import filename
import json
import os
from flask import request
from flask_restplus import Resource, Api
from werkzeug.utils import secure_filename
from APP.Application import app
from ApiConfig.ObjectConfig import Trainer, cData, Tmodal, Amodal, Cmodal
from ApiConfig.SA_utility import sentiment_sorting
from ApiConfig.appFileConfig import UPLOAD_FOLDER
from Classification.Classifier import classify
from DataBase.DB import db
from ExcelParser_DataFrame.Excel_Parser import ExcelDataFrame
from Vectorizer.Data_vector import vectorizer
from Mapper.UI_Map import UI_Map
from werkzeug.contrib.fixers import ProxyFix
api = Api(app)
app.wsgi_app = ProxyFix(app.wsgi_app)
#api.route('/sentiment-analysis/trainer')
class Upload_File(Resource):
def post(self):
..............
if __name__ == '__main__':
db.init_app(app)
db.create_all()
app.run(host='0.0.0.0')
My wsgi.py file looks like this
import sys
sys.path.insert(0, "/home/gulshan/Downloads/SA_PANDAS_SGDC/src")
from APP.Application import app
application = app
i tried using this wsgi file and started the server by firing the below command on my linux machine
uwsgi --http :5000 --wsgi-file wsgi.py --callable app --processes 4 --threads 2 --stats 127.0.0.1:9191
when i tried accessing the url using Postman then i get error as shown below:-
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<title>404 Not Found</title>
<h1>Not Found</h1>
<p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
My APP.Application file looks like this:-
from flask import Flask
from ApiConfig import Settings as settings
app = Flask(__name__)
#app.config['SERVER_NAME'] = settings.FLASK_SERVER_NAME
app.config['SQLALCHEMY_DATABASE_URI'] = settings.SQLALCHEMY_DATABASE_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = settings.SQLALCHEMY_TRACK_MODIFICATIONS
app.config['SWAGGER_UI_DOC_EXPANSION'] = settings.RESTPLUS_SWAGGER_UI_DOC_EXPANSION
app.config['RESTPLUS_VALIDATE'] = settings.RESTPLUS_VALIDATE
app.config['RESTPLUS_MASK_SWAGGER'] = settings.RESTPLUS_MASK_SWAGGER
app.config['ERROR_404_HELP'] = settings.RESTPLUS_ERROR_404_HELP
app.config['SQLALCHEMY_POOL_SIZE'] = settings.SQLALCHEMY_POOL_SIZE
#app.config['SQLALCHEMY_POOL_TIMEOUT'] = settings.SQLALCHEMY_POOL_TIMEOUT
app.config['SQLALCHEMY_POOL_RECYCLE'] = settings.SQLALCHEMY_POOL_RECYCLE
app.config['SQLALCHEMY_MAX_OVERFLOW'] = settings.SQLALCHEMY_MAX_OVERFLOW
Got a solution working for me although it seems to be weird way of doing this:-
Changed my uwsgi.py
import sys
sys.path.insert(0, "/home/gulshan/Downloads/SA_PANDAS_SGDC/src")
from APP.Application import app
from flask import Flask
from SA_APP.SA import appnew
application = app
application = appnew
and added this line in my first code snippet file containing main call
api = Api(app)
appnew = app.

Categories