Plotly in Expected Flask Window - python

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

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)

how can I deploy Dash components on html script?

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')

Why images can be shown only if they are in `static` folder?

I'm building a image recognition Flask project. And I want the image shown on the web page. Here is the structure of my project:
As you can see, static,templates and upload are in the same folder. If I save the image into static folder (which is generated by the VS2015 flask project) and write the result.html like this:
<!doctype html>
<h3>{{ outcome_info }}</h3>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<title>Flood Classifier</title>
</head>
<body>
<img src="{{url_for('static', filename=thename)}}">
</body>
</html>
The image would shown successfully when this Python function is called:
#app.route('/classify', methods=['POST','GET'])
def classify():
global image
image = np.expand_dims(image, axis = 0)
result = model.predict(image)
if result[0][0] == 1:
result = "flood"
else:
result = "no flood"
return render_template('result.html', thename = imagename, outcome_info = result)
However, if I save the image file into upload (which is created by myself), and just change the folder name in result.html like this:
<!doctype html>
<h3>{{ outcome_info }}</h3>
<html lang="zh-cmn-Hans">
<head>
<meta charset="utf-8">
<title>Flood Classifier</title>
</head>
<body>
<img src="{{url_for('upload', filename=thename)}}">
</body>
</html>
The image would not shown when call that Python function. Do the images must be saved into static folder or there is something that I misunderstand?
you can use this configuration:
from flask import Flask
app = Flask(__name__, static_url_path = "/upload", static_folder = "upload")
Then you can access your images as follows:
<img src='/upload/image1.jpg' width="200" height="85">
check this answer for more details: Cannot show image from STATIC_FOLDER in Flask template
I think you misunderstand how url_for works.
The first parameter is endpoint, endpoint is roughly a registered route handler. And static is a built-in route handler which handles all requests to http://yourserver/static/xxxx.
When you set static_folder, you set the flask to serve all files under that folder through route static. You can also override this default route by setting static_url_path.
doc

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