how can I deploy Dash components on html script? - python

I'm newbie in python Dash.
And I'm currently developing a website combine with Python Flask and HTML.
I already made some functions that shows some graph like data visualization by routing them as a independent HTML scripts.
but it was too static to deliver the insights I want to show. and I figured out Dash, and I'd like to route and deploy Dash components(like figure) on my own html scripts by integrating exist project.
As far as I known, I need to declare app.layout = html.Div([<contents>]) in advance before running server.
but by doing so, I couldn't load dash ouputs.
this is the result I want to get.
goal to achive
this is the source of app.py
import dash
from dash import dcc, html
from dash.dependencies import Input, Output
import plotly.express as px
import numpy as np
import pandas as pd
from flask import Flask, send_file, render_template, make_response, request, redirect, url_for, session, flash
server = Flask(__name__)
app = dash.Dash(__name__, server=server)
df = pd.read_csv('https://gist.githubusercontent.com/chriddyp/5d1ea79569ed194d432e56108a04d188/raw/a9f9e8076b837d541398e999dcbac2b2826a81f8/gdp-life-exp-2007.csv')
fig = px.scatter(df, x="gdp per capita", y="life expectancy",
size="population", color="continent", hover_name="country",
log_x=True, size_max=60)
app.layout = html.Div([
dcc.Graph(
id='life-exp-vs-gdp',
figure=fig
)
])
#server.route("/main")
def main():
fig = app.layout
return render_template('main.html',figure = fig)
and this is my html script, main.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>
Administrator
</title>
</head>
<body>
<h1>Hi this is the results!</h1>
<div>
<h2>Dash outputs</h2>
{{figure}}
<div>
</body>
</html>
any helps? Thank you so much in advance and happy new year!

To embed a Dash app as an iframe, run the dash app in a separate python process and then use the iframe markup to embed it by URL: <iframe src="the-url-of-your-dash-app" style="border: none;"/>
Above quote source.
I ran this for your code by using the following for main.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>
Administrator
</title>
</head>
<body>
<h1>Hi this is the results!</h1>
<div>
<h2>Dash outputs</h2>
<iframe src="./" style="width: 400px; height: 400px;"/>
<div>
</body>
</html>
and modifying main():
#server.route("/main")
def main():
fig = app.layout
return render_template('main.html')

Related

Why doesn't this html template render the scraped website data in the web browser(Python, Flask, HTML, Web-Scraping)?

Whenever I print out the scraped data in the terminal it shows the scraped data fine, but whenever I try serve it using Python Flask, the HTML template that I'm using does not render the data in the web browser. If you could help me fix this code.
Python (Flask) file:
from flask import Flask, render_template
from bs4 import BeautifulSoup as BS
import requests
src = requests.get('https://webscraper.netlify.app/').text
scraper = BS(src, 'lxml')
# head = scraper.find('main').select_one('article:nth-of-type(4)').div.text
# author = scraper.find('main').select_one('p').text
head = scraper.body.header.h1.text
snd_author = scraper.body.main.select_one('article:nth-of-type(2)').p.text
fst_article = scraper.body.main.article.div
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html', **locals())
app.run(debug=True)
HTML (view) file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width, initial-scale=2.0"/>
<title>Python Flask Web Scraper</title>
</head>
<body>
<!-- Python Flask Variables go here: -->
<h1> {{ head }} </h1>
<p>{{ snd_author }}</p>
<article>{{ fst_article }}</article>
</body>
</html>
You should instead use:
return render_template('index.html', head=head, snd_author=snd_author, fst_article=fst_article)

Plotly in Expected Flask Window

I've cobbled together a very minimal flask app example for replication of my issue. The code below generates a simple plot which I want to be displayed within the out.html file. However, running the app, a plot is created but displayed in a windows of its own.
How can I force that plot to be rendered within the out.html file in approximately the location I want? Below is the minimal flask app and a minimal html file with some jinga2.
from flask import Flask, render_template, request, session
from flask_session import Session
import plotly.express as px
server = Flask(__name__)
#server.route('/')
def visual():
df = px.data.gapminder().query("country=='Canada'")
fig = px.line(df, x="year", y="lifeExp", title='Life expectancy in Canada')
return render_template('out.html', out = fig.show())
if __name__ == '__main__':
server.run(debug=True)
Contents of out.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Test</title>
</head>
<body>
<h1>
I want the figure to be about here
</h1>
{{out}}
</body>
</html>
Instead of out = fig.show(), use out = fig.to_html(full_html=False)
Then in your HTML file, instead of {{ out }}, use {{ out|safe }}
For more information: https://plotly.com/python-api-reference/generated/plotly.io.to_html.html

Write HTML received as string to browser

I have a basic HTML file which looks like this:
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome!</h1>
</body>
</html>
I am receiving the file in python and storing it as a string. I want to know, is there a way I can write this out to a web browser?
The file is on my computer, so my goal is not to save it as an html file and then execute it, but rather execute this from within python to the browser.
I know that with JavaScript I can use Document.write() to inject content to a webpage, but that is already being done in the browser. I want to achieve something similar.
You can use flask, a simple Python web framework, to serve the string:
Using flask (pip install flask):
import flask
app = flask.Flask(__name__)
s = """
<!DOCTYPE html>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome!</h1>
</body>
</html>
"""
#app.route('/')
def home():
return s
if __name__ == '__main__':
app.debug = True
app.run()
Now, can you navigate to 127:0.0.1:5000 or the equivalent IP and port specified when the app is run.
You could do the following:
html = """<!DOCTYPE html>
<html>
<head>
<title>Home</title>
</head>
<body>
<h1>Welcome!</h1>
</body>
</html>"""
with open('html_file.html', 'w') as f:
f.write(html)
import webbrowser, os
webbrowser.open('file://' + os.path.realpath('html_file.html'))

Flask : href link to html not working

I have a basic Flask app with the following structure :
from flask import Flask
from flask import render_template
app = Flask(__name__,template_folder='E:\Programming\Python Projects\Flask')
#app.route('/')
def index():
return render_template('hello.html')
#app.route('/route/')
def route1():
return render_template('route1.html')
app.run(debug = True,port = 8080,host = '0.0.0.0')
hello.html :
<!DOCTYPE html>
<html>
<head>
<title>Rendered!!</title>
</head>
<body>
<h1>
The template has been rendered!!!<br>
Route No. 1
</h1>
</body>
</html>
route1.html :
<!DOCTYPE html>
<html>
<head>
<title>Route No. 1</title>
</head>
<body>
<h2>
This is the first route!!!<br>
Hello World!!!
</h2>
<iframe src="https://www.youtube.com/embed/YQHsXMglC9A" width="853" height="480" frameborder="0" allowfullscreen></iframe>
</body>
</html>
When I open localhost:8080 it works fine.
But when I click on the link, it says :
The address wasn’t understood
Firefox doesn’t know how to open this address, because one of the following protocols (localhost) isn’t associated with any program or is not allowed in this context.
It works fine when I type the address localhost:8080/route manually in the address bar.
Also, it works fine when opened in a new tab.
I need help!!!
Thank You !!!
You should use from flask import render_template, url_for
and in the template:
<h1>
The template has been rendered!!!<br>
Route No. 1
</h1>
Just let Flask and Jinja2 make the URL's for you...
*It seems that you forgot the trailing slash at the link.
Should be localhost:8080/route/
But its far better to use url_for as it avoids this type of problem

Bokeh Problem Rendering Plot in Flask App

My flask driven app works as expected with the high level Bar plot from Bokeh.
I now want to change the plot to a horizontal bar plot and found this SO answer.
My code minus the formatting for brevity:
from flask import Flask, render_template
from bokeh.embed import components
from bokeh.util.string import encode_utf8
from bokeh.plotting import figure
import pandas as pd
app = Flask(__name__)
#app.route('/')
def test():
kws = ["one", "two", "cat", "dog"]
count = [23, 45, 11, 87]
df = pd.DataFrame({"kw": kws,
"count": count
})
df.sort("count", inplace=True)
df.set_index("kw", inplace=True)
series = df['count']
p = figure(width=1000, height=1000, y_range=series.index.tolist())
j = 1
for k, v in series.iteritems():
w = v / 2 * 2
p.rect(x=v/2,
y=j,
width=w,
height=0.4,
color=(76, 114, 176),
width_units="screen",
height_units="screen"
)
j += 1
#### get components ####
script, div = components(p)
page = render_template('test.html', div=div, script=script)
return encode_utf8(page)
if __name__ == "__main__":
app.run(debug=True,
threaded=False
)
Located in templates/test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-0.9.0.min.css" rel="stylesheet" type="text/css">
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-0.9.0.min.js"></script>
</head>
<body>
{{ div | safe }}
{{ script | safe }}
</body>
</html>
This answer works in testing with show(p). However the actual application takes the p object and gets the components div and script and embeds those in html.
When I run the app with debug=True I do not get an error just a hanging page.
EDIT: "Hang" is not accurate. I get a blank page.
Following Bigreddot's advice, I checked my version of Bokeh and adjusted the BokehJS version to match.
conda list bokeh yielded:
bokeh 0.10.0 py27_0
I then changed my html and the minimal example works as expected.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-0.10.0.min.css" rel="stylesheet" type="text/css">
<script src="http://cdn.bokeh.org/bokeh/release/bokeh-0.10.0.min.js"></script>
</head>
<body>
{{ div | safe }}
{{ script | safe }}
</body>
</html>
In case anyone comes across this from now on please note that bokeh.util.string import encode_utf8 has been removed since bokeh==2.0.0
In my case, with a flask app (using flask==1.1.2 and bokeh==2.0.2), I was simply able to delete this line from the code and in the html render template, just return html rather than return encode_utf8(html).

Categories