This is a flask application which usually works.
My plots generated with bokeh are not showing up on the page at all. I can see that they are added to the html when I look with the tools but they're not visible. The page does not break and I can visit it as normal. I have tried everything from their page but now I just want the simplest example to work. When applied the json variant I just got a json printed on the page where the plot's supposed to be.
What have I missed?
EDIT: A minimum working example is also apreciated.
My route
from flask import Blueprint, render_template, redirect, url_for, flash
import json
from bokeh.embed import json_item, server_document, components
from bokeh.plotting import figure, curdoc
from bokeh.resources import CDN
from bokeh.sampledata.iris import flowers
from bokeh.layouts import gridplot
from bokeh.models import BoxSelectTool, LassoSelectTool
from bokeh.client import pull_session
test_bp = Blueprint(
'test_bp', __name__,
template_folder='templates',
static_folder='static'
)
#test_bp.route('/test_site', methods=['GET', 'POST'])
def test_site_view():
plot = figure()
plot.circle([1, 2], [3, 4])
script, div = components(plot)
return render_template(
'test.html',
script=script,
div=div
)
My test.html
{% extends "base.html" %}
<header>
{{ script|safe }}
</header>
{% block content %}
<h1>Plot</h1>
<div>
{{ div|safe }}
</div>
{% endblock %}
base.html includes
<head>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-2.1.0.min.js"
crossorigin="anonymous"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.1.0.min.js"
crossorigin="anonymous"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.1.0.min.js"
crossorigin="anonymous"></script>
<link href="http://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.1.0.min.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}" />
</head>
For starters, you are trying to load CDN resources that don't actually exists. Bokeh stopped publishing separate CSS files at version 2.0. Since it is important that the CDN and Python versions match, it's best to just always let Bokeh itself format the necessary resources:
#test_bp.route('/test_site', methods=['GET', 'POST'])
def test_site_view():
plot = figure()
plot.circle([1, 2], [3, 4], size=40)
script, div = components(plot)
return render_template(
'test.html',
script=script,
div=div,
resources=CDN.render()
)
works with this template:
<head>
{{ resources|safe }}
</head>
<header>
{{ script|safe }}
</header>
{% block content %}
<h1>Plot</h1>
<div>
{{ div|safe }}
</div>
{% endblock %}
Related
I am trying to embed a plot from a function that I pass into my flask application.
The below does everything fine but launches the plot outside of the browser.
I've read a lot about IO and all but I'm confused on how/where to handle that.
The function runBB() in app.py returns plt.show(). After being passed symbol which is retrieved from the form. Should I be passing fig instead to do the IO calculations in app.py or should I do that in the file that holds the function?
I don't want to save the file anywhere as I want this to be dynamic from the stand point of multiple not overwriting the saved file which is what IO gets around I believe.
app.py
#Dashboard page
#app.route("/dashboard", methods = ["POST", "GET"])
def dashboard():
if person["is_logged_in"] == True:
return render_template("dashboard.html", email = person["email"], name = person["name"])
else:
return redirect(url_for('login'))
#app.route("/form", methods = ["POST", "GET"])
def form():
if request.method == "POST":
symbol = request.form["symbol"]
bytes_obj = runBB(symbol)
return render_template("dashboard.html", symbol=bytes_obj)
dashboard.html
{% extends "layout.html" %}
{% block content %}
<head>
<title>Welcome</title>
<link rel="stylesheet" type="text/css" href="{{url_for('static', filename = 'dashboard.css')}}">
<link rel="stylesheet" type="text/css" href="../static/dashboard.css">
</head>
<body>
<div class="main">
<h1 class="name">Hi, {{name}}</h1>
<form action="{{ url_for('form') }}" method ="POST">
<p><input placeholder="Enter your symbol" type="text" name="symbol"></p>
<p><input type="submit" value="Run Report" class="btn-default"></p>
</form>
<P>{{bytes_obj}}</P>
<!-- <hr style="width: 30%"> -->
<h3 class="email">{{email}}</h3>
</div>
</body>
{% endblock %}
Can someone point me in the right direction?
I've tried to comprehend other similar stackoverflow questions and can't seem to grasp this or put it together.
Please refer to this link to learn how to do this using:
import io
import base64
https://gitlab.com/snippets/1924163
I'm currently trying out bokeh server to serve some interactive bokeh charts to my django app, but having difficulty connecting via views.py.
The browser returns an OSError:
Cannot pull session document because we failed to connect to the server (to start the server, try the 'bokeh serve' command)
The server itself returns 404 error for the request:
200-03-31 08:17:09,179 404 GET /ws?bokeh-protocol-version=1.0&bokeh-session-id=ZhGn4XcmC1qDPYtF4SRPGPa1GzSgTqktqmvkIEGJke26 (127.0.0.1) 0.55ms
My server is set up as follows:
bokeh_server
|
|--main.py
main.py is a very basic bokeh chart
main.py
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.plotting import figure
from bokeh.models.sources import ColumnDataSource
source = ColumnDataSource(dict(x=list(range(5)), y=list(range(5))))
p = figure(width=300, height=300, tools=[], toolbar_location=None, name="test")
p.line(x='x', y='y', source=source)
curdoc().add_root(column(p, sizing_mode='scale_width'))
Running the server (bokeh serve bokeh_server) and then opening https://localhost:5006 in a browser renders the chart correctly (https://localhost:5006/bokeh_server)
The issue comes when I try to open it from my django app.
views.py
from django.shortcuts import render
from django.http import HttpResponse
from bokeh.client import pull_session
def testbserver(request):
session = pull_session(url="http://localhost:5006/")
script = server_session(model=None,
session_id=None,
url="http://localhost:5006/",
)
return render(request, 'testserver.html', {'script':script})
urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.home, name='home'),
path('testbserver/', views.testbserver, name='testbserver'),
]
testserver.html
{% extends "base_generic.html" %}
{% block content %}
<div class="container-fluid">
<div class="row">
<div class="col-sm-12">
{{script | safe }}
</div>
</div>
</div>
{% endblock %}
I've tried running the server with websockets allowed (bokeh serve bokeh_server/ --allow-websocket-origin="*" --log-level trace) but still get the same error.
Any suggestions for other things to try are gratefully received!
Thanks to #Eugene Pakhomov for the pointers, needed to update views.py to:
views.py
from django.shortcuts import render
from django.http import HttpResponse
from bokeh.client import pull_session
from bokeh.embed import server_session
def testbserver(request):
session = pull_session(url="http://localhost:5006/bokeh_server")
script = server_session(model=None,
session_id=session.id,
url="http://localhost:5006/bokeh_server",
)
return render(request, 'testserver.html', {'script':script})
There was also an issue in the testserver.html - I wasn't making the script safe:
testserver.html
{% extends "base_generic.html" %}
{% block content %}
<head>
<link href = "https://cdn.pydata.org./bokeh/release/bokeh-1.4.0.min.css" rel = "stylesheet" type = "text/css" >
<link href = "https://cdn.pydata.org./bokeh/release/bokeh-widgets-1.4.0.min.css" rel = "stylesheet" type = "text/css" >
<link href = "https://cdn.pydata.org./bokeh/release/bokeh-tables-1.4.0.min.css" rel = "stylesheet" type = "text/css" >
<script type = "text/javascript" src = "https://cdn.pydata.org./bokeh/release/bokeh-1.4.0.min.js"> </script>
<script type = "text/javascript" src = "https://cdn.pydata.org./bokeh/release/bokeh-widgets-1.4.0.min.js"> </script>
<script type = "text/javascript" src = "https://cdn.pydata.org./bokeh/release/bokeh-tables-1.4.0.min.js"> </script>
<h1>Test</h1>
{{script | safe}}
</head>
<div style="margin-left:20px;margin-top:20px">
<body>
{{div | safe}}
</body>
{% endblock %}
I tried to make a flask app that gets a CSV file from the user, then fits my ML algorithm and finally shows two scatter plots.
Although I could show individual scatter plots via Markup(file_html(plot_obj, CDN, "my plot"), when I use components(plot_obj), and render_template to show both of them together it does not show any of them. Also, I have no error in the console.
I am able to upload the data, then run my algorithm and get the results in the console, however I still don't see the plots.
here is my app.py:
from prad_run import fit
from plots_anomalies import tsne_plot
from bokeh.resources import INLINE, CDN
from bokeh.plotting import figure
import os
from flask import Flask, flash, request, redirect, render_template
from pr_run import fit
from plots import tsne_plot
app = Flask(__name__)
#app.route('/',methods = ['GET'])
def home():
return render_template('home.html')
#app.route('/', methods=['POST'])
def results():
if request.method == 'POST':
file = request.files['file']
df = pd.read_csv(file)
gold_label, df_pr = fit(df)
y_pr = df_pr.loc[:, 'avg_score']
X_tsne = df_pr.drop(columns='avg_score')
tsne_value = plot(X_tsne)
p_true = figure(title="Data with True Labels",plot_width=300, plot_height=300,)
true_df = pd.DataFrame(data=tsne_value, columns=["v1", "v2"])
colormap = {1: 'red', 0: 'green'}
true_df['label'] = gold_label
true_df["color"] = true_df['label'].map(lambda x: colormap[x])
p_true.scatter(true_df['v1'], true_df['v2'], color=true_df['color'], fill_alpha=0.8, size=5)
p_pr = figure(title="Predicted results",plot_width=300, plot_height=300)
tsne_df = pd.DataFrame(data=tsne_value, columns=["v1", "v2"])
tsne_df["pr"] = [1 if x > 0.115 else 0 for x in y_pr]
colormap = {1: 'red', 0: 'green'}
tsne_df['color'] = tsne_df['pr'].map(lambda x: colormap[x])
print(tsne_df['color'].values)
p_pr.scatter(tsne_df['v1'], tsne_df['v2'], color=tsne_df['color'], fill_alpha=0.8, size=7)
js1, divs1 = components(p_true)
js2, divs2 = components(p_pr)
return render_template("home.html", js1=js1, divs1=divs1,js2=js2, divs2=divs2 )
In my home.html:
<!doctype html>
<html>
<title>Python Flask File Upload Example</title>
<h2>Select a file to upload</h2>
<p>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
</p>
<form method="post" action="/" enctype="multipart/form-data">
<dl>
<p>
<input type="file" name="file" autocomplete="off" required>
</p>
</dl>
<p>
<input type="submit" value="Submit">
</p>
</form>
<meta charset="UTF-8">
<head>
<title>Figure examples</title>
<link rel="stylesheet" href="http://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.css" type="text/css" />
<script type="text/javascript" src="http://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.js"></script>
<link
href="https://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.css"
rel="stylesheet" type="text/css">
<link
href="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.4.0.min.css"
rel="stylesheet" type="text/css">
<link
href="https://cdn.bokeh.org/bokeh/release/bokeh-tables-1.4.0.min.css"
rel="stylesheet" type="text/css">
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.4.0.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-tables-1.4.0.min.js"></script>
{{ script|safe }}
</head>
<body>
<div style="width: 20%; display: inline-block;">
{{ divs1 | safe }}
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.4.0.min.js"></script>
{{ js1 | safe }}
</div>
<div style="width: 20%; display: inline-block;">
{{ divs2 | safe }}
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.4.0.min.js"></script>
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-widgets-1.4.0.min.js"></script>
{{ js2 | safe }}
</div>
</body>
</html>
Any idea what is causing this problem?
The <script> tags returned by components have to go in the <head> not <body>. Additionally, you don't need to load BokehJS from CDN multiple times as you are doing above.
You might also want to consider the newer json_items API for embedding, which can be simpler in many cases:
https://docs.bokeh.org/en/latest/docs/user_guide/embed.html?highlight=components#json-items
I found out that the reason that my plots did not display was using Conda environment. If you use Bokeh and Flask I encourage you to use virtualenv in the same folder that you are making your app instead of creating Conda environment.
I am trying to create map in Django using folium. There is no error message, but instead of the map it displays the word 'None'.
I have a django web app that reads from a postgressql database and displays the records. That is working. I want to add a map with markers, and the markers will get coordinates from the postgresql data. When I try to create a map using iframe, I get the word 'None'. I have tried just hard coding a starting location to just create the map. I still get the word 'None'.
I also typed the hard coded coordinates into google maps, and made a flask app that creates the map. They show up fine.
views.py:
from django.shortcuts import render
from django.http import HttpResponse
from .models import PhotoInfo
import folium
import pandas
# Create your views here.
def index(request):
VarPhotoInfo = PhotoInfo.objects.order_by('DateTaken')
context = {'PhotoInfo': VarPhotoInfo }
return render(request,'natureapp/index.html',context)
def show_map(request):
#creation of map comes here + business logic
#PhotoInfo1 = PhotoInfo.objects.order_by('DateTaken')
map = folium.Map(location=[33.57137166666667, -117.76325])
map.save("natureapp/map.html")
context = {'my_map': map }
return render(request, 'natureapp/map.html', context)
map.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>NatureMapper</title>
</head>
<h1>Map goes here </h1>
{{ my_map.render }}
</html>
index.html:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>NatureMapper</title>
</head>
<h1>Here it is! </h1>
{% if PhotoInfo %}
{% for Photo in PhotoInfo %}
<p>there is info.</p>
<p> {{ Photo.PhotoName }}</p>
<p> {{ Photo.Lat }}</p>
<p> {{ Photo.Long }}</p>
<p> <img src="{{ Photo.PhotoImage.url }}" width = "240" alt=""></p>
{% endfor %}
{% else %}
<p>there is no info.</p>
{% endif %}
<iframe id="encoder_iframe" height=95% width="90%" src="{% url 'show_map' %}">
</iframe>
</html>
There is no error message. Just the word 'None'
I have a csv file and need to convert it to view it in html. I know python pandas can do it with
df = pd.read_csv("myfile.csv")
df.to_html('output.html')'
but I don't want to show it in single web page, I have index.html file and I want to show it in there but in another section.
found the answer using tablib
from flask import Flask, render_template
import tablib
import os
app = Flask (__name__)
dataset = tablib.Dataset()
with open(os.path.join(os.path.dirname(__file__),'email.csv')) as f:
dataset.csv = f.read()
#app.route("/")
def index():
data = dataset.html
#return dataset.html
return render_template('index.html', data=data)
if __name__ == "__main__":
app.run()
index.html
<html>
<head>
<meta charset="utf-8" />
<link rel=stylesheet type=text/css href="{{ url_for('static',
filename='css/style.css') }}"/>
<title>Show CSV</title>
</head>
<body>
<div class="table">
{% block body %}
{{ data|safe }}
{% endblock %}
</div>
</body>
</html>