Bokeh plot not showing in Flask - html

Problem: My Bokeh plot, implemented with Flask, is not showing in my browser. When I run the app, the Bokeh frame (with the tools), as well as the x-axis label show up, but no data is plotted inside.
Already tried: I've made sure that the Bokeh version mentioned in the HTML files is as others have suggested. I'm pretty sure I've exhausted the SO solutions presented already. I've used print statements throughout the program and determined that the data is actually collected, cleaned, and processed with the components module and passed to 'script'. So therefore, as far as I can tell, the code seems to be stuck at the 'last render_template line?
from flask import Flask, render_template, request, redirect, session
import pandas as pd
import quandl
from bokeh.plotting import figure, output_file, save
from bokeh.embed import components
from bokeh.io import show
app = Flask(__name__) #create an instance of the flask class (named 'app') in the current file
app.vars={}
#app.route('/')
def main():
return redirect('/index')
#app.route('/index', methods=['GET'])
def index():
return render_template('index.html')
#app.route('/plot', methods=['POST'])
def plot():
app.vars['current_symbol'] = request.form['current_symbol']
quandl.ApiConfig.api_key = 'CD38JS9JqAdmdeio9JPW'
req_data = quandl.get_table('WIKI/PRICES', ticker=app.vars['current_symbol'], qopts = {'columns':['ticker', 'date', 'adj_close']}, date = {'gte': '2017-11-01', 'lte': '2017-12-01'}, paginate = True)
req_data.adj_close = round(req_data.adj_close, 2)
req_data = req_data.set_index('date')
cleaned_data = req_data.pivot(columns = 'ticker')
# Plot the data
p = figure(x_axis_type='datetime', x_axis_label='Date', y_minor_ticks=2, plot_width = 800, plot_height = 600)
p.line(x = cleaned_data.index, y = cleaned_data.adj_close, line_width = 2)
script, div = components(p)
return render_template('plot.html', script=script, div=div)
if __name__ == "__main__":
app.run(debug=True)
Here are the accompanying HTML files.
index.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Stock Plotter</title>
<link href="https://cdn.bokeh.org/bokeh/release/bokeh-1.2.0.min.css" rel="stylesheet" type="text/css">
<script src="https://cdn.bokeh.org/bokeh/release/bokeh-1.2.0.min.js"></script>
<!-- <link rel="icon" href="favicon.ico"> -->
<title>Stock Plotter</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
</head>
<body>
<div class=metanav>
<h1>Stock Plotter</h1>
<div>
<form id="tickerform" action="/plot" method="POST">
Ticker Symbol: <input type="text" name="current_symbol" placeholder="ticker symbol"></input> <!--Create a dropdown list with the following options=-->
<div>
<input type="submit" value="Submit"></input> <!--Create the submit button-->
</div>
</form>
</div>
{{ script|safe }} <!--Marks the js scrips as safe for the web-->
{{ div|safe }}
<!-- Bootstrap core JavaScript
================================================== -->
<!-- Placed at the end of the document so the pages load faster -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
</body>
</html>
plot.html
<html lang="en">
<head>
<meta charset="UTF-8">
<link href="https://cdn.bokeh.org/bokeh/release/bokeh-1.2.0.min.css" rel="stylesheet" type="text/css">
<script src="https://cdn.bokeh**strong text**.org/bokeh/release/bokeh-1.2.0.min.js"></script>
<title>Stock Plotter</title>
</head>
<body>
<div class=page>
<h1>Stock Plotter</h1>
{{ script|safe }}
{{ div|safe }}
</div>
</body>
</html>
I expect the plot to be visible, but it's not.
No error messages are shown in the console.

Check this post:
Embedding multiple bokeh HTML plots into flask
It has a great example as to how to display bokeh figures in flask apps.

For anyone looking for an answer, the problem with this code is that the plot definition (p.line...) has some problem with my defining the x and y values explicitly. Once I used the source argument, the plot appears as desired.

Related

Pass Jinja2 template as html string while rendering using FastAPI?

My template is as follows:
<!-- template1.html -->
<html>
<head>
<title>Item Details</title>
</head>
<body>
<p>{{ req }}</p>
</body>
</html>
To render the template I am using the following code:
from fastapi import FastAPI
from fastapi.templating import Jinja2Templates
app = FastAPI()
template = Jinja2Templates(directory="templates")
#app.get("/list_items")
def home(request: Request):
return template.TemplateResponse('template1.html',{"req": req})
#app.get("/", response_class=HTMLResponse)
async def read_items():
return """
<html>
<head>
<title></title>
</head>
<body>
<form action="/list_items">
<input type="text" placeholder="Search.." name="search">
<button type="submit">Search</button>
</form>
</body>
</html>
"""
But I do not want to use a separate folder with files for a simple template. How do I pass the html text instead of the function TemplateResponse
You can use HTMLResponse. Pass HTMLResponse as the parameter response_class of your route.
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
#app.get("/items", response_class=HTMLResponse)
def read_items():
return """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
You can also override the response directly in your endpoint, by returning it.
from fastapi import FastAPI
from fastapi.responses import HTMLResponse
app = FastAPI()
#app.get("/items")
def read_items():
html_content = """
<html>
<head>
<title>Some HTML in here</title>
</head>
<body>
<h1>Look ma! HTML!</h1>
</body>
</html>
"""
return HTMLResponse(content=html_content, status_code=200)
Update
Jinja2Templates.TemplateResponse expects as name parameter a filename that is pointing to the template your would like to return, and which lies in the Jinja2Templates directory you defined (e.g., Jinja2Templates(directory="templates") ). You can't pass the template contents to its place. Jinja2Templates will attempt to retrieve the file you passed using the directory you defined earlier, see here -> here -> here. Hence, what you are asking, it doesn't seem to be natively possible (but, with some hackish stuff maybe doable); however, there is nothing wrong with having a templates directory, even for small template files.

Have CSS connected in HTML in a Flask project

<!DOCTYPE html>
<html lang="en">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Page</title>
<link rel="stylesheet" href="{{ url_for('static', filename='styles.css') }}">
</head>
<body>
<div class = "tela">
<h1>Login</h1>
<form action="/" method = "post">
<input class = "inf" type="text" placeholder="Email">
<br><br>
<input class = "inf" type="password" placeholder="Senha">
<br><br>
<button class = "main-btt">Log in</button>
</form>
<form action="/criarconta" method="post">
<button class = "criar">Criar conta</button>
</form>
</div>
</body>
</html>
from flask import Flask, request, render_template, redirect
app = Flask("__name__")
#app.route("/")
def index():
return render_template("login.html")
#app.route("/criarconta", methods=["POST"])
def create():
return render_template("criarconta.html")
I'm working on a Login page, with flask, html and css, but always that I run flask the link that shows up is a html page without css, even when I link css in the html file. I want to resolve tis, and finds out how to open the page and the css is there. OBS: When I open the file alone, without flask, it works.
I tried using href="styles.css" but it didn't work so I changed for url_for, but its still not working.
I think the problem is in the html but I putted the python if you need.

Why is Flask not loading images the second time I render a template?

I have made a ML model which I am deploying in a website using Flask. This is the code for it:
main.py
#imports
app = Flask(__name__)
def check(url):
#function to check whether the URL entered by user is Phishing or not and return the result
#app.route('/')
def home():
return render_template("home.html") #renders homepage template
#app.route('/phish/<url>')
def phish(url):
for i in range(0,len(url)):
if url[i]=="$":
url = url[:i]+"/"+url[i+1:] #changing url back to original
return render_template("phish.html", url=url)
#app.route('/safe/<url>')
def safe(url):
for i in range(0,len(url)):
if url[i]=="$":
url = url[:i]+"/"+url[i+1:] #changing url back to original
return render_template("safe.html", url=url)
#app.route('/', methods=['POST'])
def results():
url = request.form['url']
result = check(url)
for i in range(0,len(url)):
if url[i]=="/":
url = url[:i]+"$"+url[i+1:] #changing "//" to "$$"
if result==1 :
return redirect(url_for("phish", url=url))
else :
return redirect(url_for("safe", url=url))
if __name__ == '__main__':
app.run()
home.html
<!DOCTYPE html>
<html lang="en">
<head>
<!-- bunch of meta tags -->
<title>PhishLearn</title>
<link href="{{ url_for('static', filename='css/bootstrap.css') }}" rel="stylesheet">
<link href="{{ url_for('static', filename='css/main.css') }}" rel="stylesheet"> <!-- for loading
css -->
</head>
<body>
<!-- body code -->
<script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="static/js/bootstrap.min.js"></script>
</body>
</html>
The code for phish.html and safe.html is also exactly same except for some changes in the body part.
Now when I initially run my main.py file the home page is loaded perfectly. But when I input a URL and click submit the page that is then rendered according to the result (phish or safe) does not display any image. Here are the screenshots of the pages:
Homepage
Result Page
As you can see when safe.html is rendered it does not shows any images. Can anyone tell me why this is happening and how to solve this issue?
I just use the src attribute of img tag to specify the path of file. Since all my html resources (css, js, images, etc.) are inside the static folder so I write src = "static/img/image-name.jpg"
That's your problem (as I kind of guessed).
When the URL in your browser is /phish/foople.blarp.quux, then static/img/image-name.jpg relative to that path is /phish/foople.blarp.quux/static/img/image-name.jpg which obviously 404s.
You need to
use the {% url_for("static", filename=...) %} form so Flask will deal with forming the correct static URL,
or alternately but less preferably (since changing the static files' root path will then require you to edit every template you have) use an absolute path /static/img/image-name.jpg.
or if you feel like using esoteric and often-forgot-about HTML features, set <base> and never worry about relative paths, but really please don't do that.

FLASK - HTML - requested URL was not found

I'm new to html, i have researched a lot, but cannot solve this issue. I'm sure for you it is trivial, but I stuck.
So
I have a flask webserver. that is the code:
it is so simple, just loading the home.html and I guess the issue will be here somewhere, but I cannot find it.
all html docs are in the same folder, in the templates. the home.html loading nicely, but nothing other. I mean if I change in the return render_template the html it will be loaded, but not throug the webpage by clicking.
from flask import Flask, render_template
app = Flask(__name__, template_folder='templates')
#app.route('/')
def home():
template_table = {
'title': "Home Control System"
}
return render_template('home.html', **template_table)
#app.route('/')
def lakas():
return render_template('lakas.html')
if __name__=='__main__':
app.run(debug=True, host='0.0.0.0')
this is the home.html code:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{{ title }}</title>
<link rel="stylesheet" type="text/css" href="../static/css/style.css?version=15">
<script type="text/javascript" src="../static/js/scripts.js?version=2"></script>
</head>
<body onload="renderTime()">
<div class="wrapper">
<div style="font-size: 1.5em", style="font-weight: bold">Menü</div>
<div class="nested_1">
<div align="right">Home Control System</div>
<div id="clockDisplay" align="right"></div>
</div>
<div class="nested_2">
Főoldal
Lakás
Garázs
</div>
<iframe src="overview.html" name="targetframe" allowTransparency="true" scrolling="no" frameborder="0"></iframe>
</div>
</body>
</html>
the folder structure is:
main
static
templates
home.html
lakas.html
garazs.html
and if I simple open the home.html everything works perfectly, I can click on the buttons(Főoldal, Lakás, Garázs)
but, when I run the flask app and I reach that through the IP I have the home page, but 404 for the rest of them. I attach picture about the ok screen and the 404.
Not found screen
OK screen
What should I change? Could you help me please?
Both your routes are the same? I'm assuming lakas should be its own page so you should change #app.route('/') to #app.route('/lakas')
#app.route('/')
def home():
template_table = {
'title': "Home Control System"
}
return render_template('home.html', **template_table)
#app.route('/')
def lakas():
return render_template('lakas.html')
Change the url in home.html to Lakás
I think you might be having trouble understanding routes. An understanding of MVC might help.

werkzeug.routing.BuildError: with flask app image gallery

I am following this video to create an image gallery using flask and python https://www.youtube.com/watch?v=yO_XNCsBIsg&t=636s
I these github files for (coppied the #app.route('/gallery')) app.py and gallery.html and ran the exact code but I am getting an error:
werkzeug.routing.BuildError: Could not build url for endpoint 'send_image' with values ['filename']. Did you mean 'index' instead?
Here is my exact code
main.py
#!/usr/bin/env python
from flask import Flask, request, send_from_directory, flash, redirect, render_template, request, url_for,jsonify
#https://stackoverflow.com/questions/32019733/getting-value-from-select-tag-using-flask
# reference to code is from https://pythonprogramming.net/jquery-flask-tutorial/
# and from https://www.blog.pythonlibrary.org/2017/12/13/flask-101-how-to-add-a-search-form/
app = Flask(__name__)
# this runs in the background for registering the compnay link that was put in
#app.route('/background_process')
def background_process():
lang = request.args.get('proglang', 0, type=str)
#just checking what was typed, this will be put into a python code eventrually
return jsonify(result=lang)
#app.route('/')
def index():
return render_template('interactive.html', data=[{'name':'red'}, {'name':'green'}, {'name':'blue'}])
filename = request.args.get('proglang')
#app.route("/black" , methods=['GET', 'POST'])
def black():
select = request.form.get('comp_select')
if select=="blue":
return(str("hi")) # just to see what select is
else:
return(str("bye"))
import os
#app.route('/gallery')
def get_gallery():
image_names = os.listdir('./images')
print(image_names)
return render_template("gallery.html", image_names=image_names)
if __name__=='__main__':
app.run(host='127.0.0.1', port=8080, debug=True)
gallery.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"
integrity="sha384-1q8mTJOASx8j1Au+a5WDVnPi2lkFfwwEAa8hDDdjZlpLegxhjVME1fgjWPGmkzs7" crossorigin="anonymous">
</head>
<body>
<div class="container">
<div class="row">
<div class="col-lg-12">
<h1 class="page-header">Thumbnail Gallery</h1>
</div>
{{image_names}}
<hr>
{% for image_name in image_names %}
<div class="col-lg-3 col-md-4 col-xs-6 thumb">
<img class="img-responsive" src=" {{url_for('send_image', filename=image_name)}}">
</div>
{% endfor %}
</div>
</div>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"
integrity="sha384-0mSbJDEHialfmuBBQP6A4Qrprq5OVfW37PRR3j5ELqxss1yVqOtnepnHVP9aJ7xS"
crossorigin="anonymous"></script>
</body>
</html>
I'm leaving out my other html files because they aren't needed for my testing of the gallery route.
You are missing the "send_image" route in your Python code:
#app.route('/upload/<filename>')
def send_image(filename):
return send_from_directory("images", filename)