Bokeh Problem Rendering Plot in Flask App - python

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

Related

how can i show css animation in my html using flask?

im a begginer here , struggling with basic stuff
I have my flask:
from flask import Flask , render_template , send_file , send_from_directory
import os
app = Flask(__name__)
#PRIMERA FUNCION
#app.route('/')
def index():
return render_template('prueba.html')
and i have my html :
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>CodePen - The Arrow</title>
<link rel="stylesheet" href="./style.css">
</head>
<body>
<!-- partial:index.partial.html -->
<div class="arrow-1"></div>
<!-- partial -->
</body>
</html>
when I open the html file on browser it shows the css ,
but when I run flask css doesnt show and I cant figure out why!!!
I have try this
#app.route('/css/<path:filename>')
def css_file(filename):
file_path = os.path.join('css', filename)
return send_file(file_path)
and i also thought it was a problem of my folder layout but I already tried re arrange folders
Flask has different ways to do this, but the convention is to put static assets (like CSS) in the static directory (which should be at the root of your project) and link them in with Jinja and the url_for() function. so in your case it would look like this:
<!DOCTYPE html>
<html lang="en" >
<head>
<meta charset="UTF-8">
<title>CodePen - The Arrow</title>
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
</head>
More explained in the Flask docs

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

Using FontAwecome icon in Flask table

I have a pandas dataframe that I'm displaying as HTML in my Flask app and would like to add a Font Awesome icon as a column in that table and repeat it based on a count for each group. For example, in this scenario:
Group
Count
Icon
A
1
B
2
I want the icon to be repeated once for Group A and twice for Group B. I'm able display icons in my navbar after downloading the flask-fontawesome package. The unicode/<i> tag (not sure which one is needed) are:

<i class="fa fa-trophy" aria-hidden="true"></i>
same way as you would include a font-awesome icon in HTML. Within a <span> with appropriate class
repeat <span> as many times as required
consider need to undo escaping of < and >
this is running in Jupyter, but same would be true for flask
import io
import pandas as pd
df = pd.DataFrame({'Group': ['A', 'B'], 'Count': [1, 2]})
df = df.assign(Icon=df["Count"].apply(lambda n: n*'<span class="fab fa-docker"></span>'))
from IPython.core.display import display, HTML
display(HTML(df.to_html().replace("<","<").replace(">",">")))
integrated into flask
same code used to generate font awesome icons based on Count
undone escaping of < and >
included link to needed CDN for font awesome
simple approach of using f-string to generate a html document
import pandas as pd
from flask import Flask, render_template, Response, jsonify
app = Flask(__name__)
#app.route('/')
#app.route('/home')
def home():
df = pd.DataFrame({'Group': ['A', 'B'], 'Count': [1, 2]})
df = df.assign(Icon=df["Count"].apply(lambda n: n*'<span class="fab fa-docker"></span>'))
return f"""<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css" integrity="sha512-iBBXm8fW90+nuLcSKlbmrPcLa0OT92xO1BIsZ+ywDWZCvqsWgccV3gFoRBv0z+8dLJgyAHIhR35VZc2oM/gI1w==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<title>SO example</title>
</head>
<body>
{df.to_html().replace("<","<").replace(">",">")}
</body>
</html>"""
if __name__ == '__main__':
app.run(debug=True, port=3000)

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

Categories