Error while sending a plot to html in flask - python

I am using flask web server and want to do the following functionality.
Pass form data from home.html to python func plot_perf_metric().
Save form data and call plot.html.
plot.html calls output_plot() which generates a plot based on the saved form data and accessing values from a database(mongodb).
plot.html prints this plot.
I am currently not getting the image displayed.
I only get a broken link of the image.
Can someone help me?
home.html
<!DOCTYPE html>
<html lang="en">
<body>
<form action="./plot" method="POST">
<input type="radio" name="perf_metric" value="disk"> Disk <br><br>
<input type="radio" name="perf_metric" value="memory"> Memory <br><br>
<input type="radio" name="perf_metric" value="cpu"> CPU <br><br>
<input type="radio" name="perf_metric" value="egress"> Egress <br><br>
<input type="radio" name="perf_metric" value="flit"> Flit <br><br>
<input type="submit" name="submit_plot" value="Send">
</form>
</body>
</html>
routes.py
from flask import Flask, render_template, send_file
from flask import request,make_response
from pymongo import MongoClient
import matplotlib.pyplot as plt
from matplotlib.figure import Figure
import StringIO
from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas
import random
app = Flask(__name__)
#app.route('/')
def home():
return render_template('home.html')
def connect_mongo(text):
client = MongoClient()
db = client['mydb']
collection = db['vload']
b = list()
a = list(collection.find())
for i in range(len(a)):
b.append(a[i][text])
return b
#app.route('/output')
def output_plot():
fig = Figure()
axis = fig.add_subplot(1, 1, 1)
b=connect_mongo(plot_perf_metric.text)
fig = axis.plot(b)
output = StringIO.StringIO()
response = make_response(output.getvaluest())
response.mimetype = 'image/png'
fig.savefig(output)
output.seek(0)
return send_file(output, mimetype='image/png')
#app.route('/plot',methods=['POST'])
def plot_perf_metric():
if(request.form['submit_plot'] == "Send"):
text = request.form['perf_metric']
return render_template('plot.html')
if __name__ == '__main__':
app.run(debug=True)
plot.html
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>Plot</title>
</head>
<body>
<img src="{{ url_for('output_plot') }}" alt="Image Placeholder" height="100">
</body>
</html>

You need to add a route for output_plot.
#app.route('/output')
def output_plot():
fig = Figure()
axis = fig.add_subplot(1, 1, 1)
b=connect_mongo(plot_perf_metric.text)
fig = axis.plot(b)
output = StringIO.StringIO()
response = make_response(output.getvaluest())
response.mimetype = 'image/png'
fig.savefig(output)
output.seek(0)
return send_file(output, mimetype='image/png')

Related

AttributeError: dict object has no attribute 'predict'

I can't use my predict method when assigning my random forest regression model to user input in flask. It give me this error:
AttributeError: dict object has no attribute 'predict'
This is my app.py code:
from flask import Flask, render_template, request
import jsonify
import requests
import pickle
from sklearn.ensemble import RandomForestRegressor
import numpy as np
import sklearn
import os
from sklearn.preprocessing import StandardScaler
app = Flask(__name__)
model = pickle.load(open('random_forest_regression_model.pkl', 'rb'))
#app.route('/', methods=['GET'])
def Home():
return render_template('index.html')
standard_to = StandardScaler()
#app.route('/api', methods=['POST'])
def predict():
Fuel_Type_Diesel = 0
if request.method == 'POST':
Year = int(request.form['Year'])
Present_Price = float(request.form['Present_Price'])
Kms_Driven = int(request.form['Kms_Driven'])
Kms_Driven2 = np.log(Kms_Driven)
Owner = int(request.form['Owner'])
Fuel_Type_Petrol = request.form['Fuel_Type_Petrol']
if Fuel_Type_Petrol == 'Petrol':
Fuel_Type_Petrol = 1
Fuel_Type_Diesel = 0
else:
Fuel_Type_Petrol = 0
Fuel_Type_Diesel = 1
Year = 2020 - Year
Seller_Type_Individual = request.form['Seller_Type_Individual']
if Seller_Type_Individual == 'Individual':
Seller_Type_Individual = 1
else:
Seller_Type_Individual = 0
Transmission_Mannual = request.form['Transmission_Mannual']
if Transmission_Mannual == 'Mannual':
Transmission_Mannual = 1
else:
Transmission_Mannual = 0
prediction = model.predict([[Present_Price, Kms_Driven2, Owner, Year, Fuel_Type_Diesel, Fuel_Type_Petrol,
Seller_Type_Individual, Transmission_Mannual]])
output = round(prediction[0], 2)
if output < 0:
return render_template('index.html', prediction_text="Sorry you cannot sell this car")
else:
return render_template('index.html', prediction_text="You Can Sell The Car at {}".format(output))
else:
return render_template('index.html')
if __name__ == '__main__':
app.run(port=5000, debug=True)
My HTML code (index.html)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div style="color:red">
<form action="{{ url_for('predict')}}" method="post">
<h2>Predictive analysis</h2>
<h3>Year</h3>
<input id="first" name="Year" type="number ">
<h3>What is the Showroom Price?(In lakhs)</h3><br><input id="second" name="Present_Price" required="required">
<h3>How Many Kilometers Drived?</h3><input id="third" name="Kms_Driven" required="required">
<h3>How much owners previously had the car(0 or 1 or 3) ?</h3><br><input id="fourth" name="Owner" required="required">
<h3>What Is the Fuel type?</h3><br><select name="Fuel_Type_Petrol" id="fuel" required="required">
<option value="Petrol">Petrol</option>
<option value="Diesel">Diesel</option>
<option value="Diesel">CNG</option>
</select>
<h3>Are you A Dealer or Individual</h3><br><select name="Seller_Type_Individual" id="resea" required="required">
<option value="Dealer">Dealer</option>
<option value="Individual">Individual</option>
</select>
<h3>Transmission type</h3><br><select name="Transmission_Mannual" id="research" required="required">
<option value="Mannual">Manual Car</option>
<option value="Automatic">Automatic Car</option>
</select>
<br><br><button id="sub" type="submit ">Calculate Selling Price</button>
<br>
</form>
<br><br><h3>{{ prediction_text }}<h3>
</div>
</body>
</html>
Error
line 70, in predict
prediction = model.predict([[Present_Price, Kms_Driven2, Owner, Year, Fuel_Type_Diesel, Fuel_Type_Petrol,
AttributeError: type object 'dict' has no attribute 'predict'
Line 70
prediction = model.predict([[Present_Price, Kms_Driven2, Owner, Year,
Fuel_Type_Diesel, Fuel_Type_Petrol,Seller_Type_Individual,
Transmission_Mannual]])
It appears the object saved in the file random_forest_regression_model.pkl is a dictionary. The data in that file seems to be wrong. You can try confirming that by printing type(model) after the line at the beginning where you load it using pickle.
You should create an object of the type that you actually want model to be and save it in that file. Then try running again.

Python Forex Calculator Not Complying

I'm trying to complete a forex money converter in FLASK but my code isn't working.
It allows the user input, then once I hit submit the next page that shows Method Not Allowed
The method is not allowed for the requested URL.
-Update, now it just goes to an action page, whenever I try to pull up the Index2.html it doesn't load. I'm not sure why its not allowing me to proceed.
-I'm trying to save three inputs, add them to a list, then convert them into a dollar amount
-Page Refreshes to action page, this is not what is intended
Index.html file
><!DOCTYPE html>
<html>
<body>
<h2>HTML Forms</h2>
<form action="/index2.html", method="Post">
<label for="C1" name= "C1"> Converting From:</label><br>
<input type="text" id="C1" name="C1"><br>
<label for="C2">Converting To:</label><br>
<input type="text" id="C2_to" name="C2_to"><br>
<label for="amt">Amount:</label><br>
<input type="text" id="amt" name="amt"><br>
<br>
<input type="submit" value="Submit">
</form>
app.py file
from flask import Flask, render_template,request, redirect, session
from forex_python.converter import CurrencyCodes, CurrencyRates
app = Flask(__name__)
app.config["secret key"]="yeah"
app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False
responses_key= "responses"
#app.route("/")
def show_form():
return render_template("Index.html" )
#app.route("/index2")
def show_form2():
return render_template("index2.html" )
T= CurrencyRates()
#app.route("/Index2", methods=["POST"])
def save_answer():
line2 = request.data.get("C1", "C2", int("amt"))
responses = session[responses_key]
responses.append(line2)
responses = session[responses]
rate = T.convert(line2[0],line2[1],int(line2[2]))
return rate,render_template("/Index2.html", rate="response")
As index2.htlm is not shared, i created a simple 1 liner index2.html to show the conversion. PFB code:
app.py:
from flask import Flask, render_template, request, redirect, session, url_for
from forex_python.converter import CurrencyCodes, CurrencyRates
app = Flask(__name__)
app.config["secret key"] = "yeah"
app.config['DEBUG_TB_INTERCEPT_REDIRECTS'] = False
responses_key = "responses"
#app.route('/', methods = ['GET', 'POST'])
def index():
return render_template('Index.html')
T = CurrencyRates()
#app.route("/conversion", methods = ['GET', 'POST'])
def conversion():
if request.method == 'POST':
C1 = request.form.get('C1', None)
C2_to = request.form.get('C2_to', None)
amt = request.form.get('amt', None)
rate = T.convert(C1, C2_to, int(amt))
print(C1, C2_to, amt, rate)
details = {'C1': C1, 'C2_to': C2_to, 'amt': amt, 'rate': rate}
return render_template("Index2.html", details=details)
if __name__ == '__main__':
app.run(host='xx.xx.xx.xx', debug=True)
app.run(debug=True)
Index.html:
<!DOCTYPE html>
<html>
<body>
<h2>HTML Forms</h2>
<form action="{{ url_for('conversion') }}" method="post">
<label for="C1" name= "C1"> Converting From:</label><br>
<input type="text" id="C1" name="C1"><br>
<label for="C2_to" name= "C2_to">Converting To:</label><br>
<input type="text" id="C2_to" name="C2_to"><br>
<label for="amt">Amount:</label><br>
<input type="text" id="amt" name="amt"><br>
<br>
<input type="submit" value="Submit">
</form>
Index2.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
</head>
<body>
<p> Conversion of {{ details.amt }} {{ details.C1 }} to {{ details.C2_to }} is: {{ details.rate }}</p>
</body>
</html>
Output:
homepage:
conversion page:

Why is my form trying to submit to the wrong endpoint?

I have a python script and a mongoDB instance.
With flask I now want to list all the items of my database on a webpage and use a second webpage to trigger the script to add an other item.
But everytime I click "submit" on the "/add" page, I get a "Method not allowed" and I can see, that it tries to submit it to "/" instead of "/add" ..
script.py
from flask import Flask, render_template, request
import requests, json, sys, getopt, smtplib
from os import system, name
from pathlib import Path
from pymongo import MongoClient
client = MongoClient(port = 27017)
db = client.amazonProducts
allitems = []
allMyItems = []
for document in db.items.find():
allitems.append(document["name"])
def addItem():
for dbWishList in db.wishlist.find():
url = dbWishList["wishlist"]
items = json.loads(requests.get(url).text)
if items:
for item in items:
itemName = str(item["name"])
itemPrice = item["new-price"]
itemUrl = str(item['link'])
if itemPrice:
itemPrice = str(itemPrice[26: ])
itemPrice = str(itemPrice[: itemPrice.find("<")])
itemPriceF = str(itemPrice.replace(".", ""))
itemPriceF = str(itemPriceF.replace("€", ""))
itemPriceF = str(itemPriceF.replace("\xa0", ""))
itemPriceF = str(itemPriceF.replace(",", ".")).replace("\xf6", "")
itemPriceFi = float(itemPriceF)
itemUrl = itemUrl[: itemUrl.find("?coliid")]
itemNameF = itemName.replace('"', '"')
itemNameFi = itemNameF.replace("&amp;", "&")
itemNameFi = itemNameFi.replace("ü", "ue").replace("ö", "oe").replace("ä", "ae").replace(" ", " ").replace("–", "-")
amazonItem = {
'name': itemNameFi,
'url': itemUrl,
'price': itemPriceFi,
'maxPrice': 0
}
db.items.insert_one(amazonItem)
for document in db.items.find():
allMyItems.append(document["name"])
return allMyItems
app = Flask(__name__)
#app.route('/')
def homepage():
return render_template("index.html", len = len(allitems), allitems = allitems)
app.run(use_reloader = True, debug = True)
app.config["DEBUG"] = True
#app.route("/add", methods = ["GET", "POST"])
def secPage():
errors = ""
if request.method == "POST":
global testingVar
testingVar = None
try:
testingVar = string(request.form["testingVar"])
except:
errors += "<p>{!r} is not a string.</p>\n".format(request.form["testingVar"])
if testingVar is not None:
addItem()
return render_template("secIndex.html", len = len(allMyItems), allMyItems = allMyItems)
return '''
<html>
<body>
{errors}
<p>What you wanna do?:</p>
<form method="post" action=".">
<p><input name="testingVar" /></p>
<p><input type="submit" value="Do magic" /></p>
</form>
</body>
</html>
'''.format(errors=errors)
index.html
<!DOCTYPE html>
<html>
<head>
<title>For loop in Flask</title>
</head>
<body>
<ul>
<!-- For loop logic of jinja template -->
{%for i in range(0, len)%}
<li>{{allitems[i]}}</li>
{%endfor%}
</ul>
</body>
</html>
secIndex.html
<!DOCTYPE html>
<html>
<head>
<title>For loop in Flask</title>
</head>
<body>
<!-- For loop logic of jinja template -->
<form method="post" action=".">
<p><input name="testingVar" /></p>
<p><input type="submit" value="Do magic" /></p>
</form>
</body>
</html>
The items are built like:
amazonItem = {
'name': itemNameFi,
'url': itemUrl,
'price': itemPriceFi,
'maxPrice': 0
}
Can anyone here follow me and tell me where my mistake might be?
In your form definition you have:
<form method="post" action=".">
The action attribute needs to have the endpoint you want to send the post request to. In your case, you want
<form method="post" action="/add">
If you omit the action attribute, it will submit the post request to the current page, so if you are viewing your form from /add, you can just use
<form method="post">

Flask: how to update div after processing form inputs

My Flask app does calculations based on user form inputs. These calculation take about 10 seconds to complete. The output of those calculations need to be displayed in a div on the same page, next to the form (in a chart / table etc).
I have tried two aproaches. The first, using normal just Flask, reloads the whole page, which is far from ideal. The second approach, using Sijax, updates just the div. But in this case, i don't know how to access the form inputs.
I'm confused how to get this working. Would appreciate any directions!
Approach 1: just flask (downside: whole page reloads)
form_test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Testpage</title>
</head>
<body>
<form action="{{ url_for('do_the_math') }}" method="post">
A = <input type="number" name="input_A">
B = <input type="number" name="input_B">
<input type="submit" value="Submit">
</form>
<div id="destination_div">A + B = {{ result }}</div>
</body>
</html>
app_normal.py:
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route("/")
def show_home():
return render_template("form_test.html", result='unknown yet')
#app.route("/do_the_math", methods=['POST'])
def do_the_math():
A = request.form.get('input_A')
B = request.form.get('input_B')
sum = float(A) + float(B)
# reloads whole page
return render_template("form_test.html", result=sum)
# what i want: reload just update destination_div with new HTML
# return render_template("#destination_div", "A + B = " + str(sum))
if __name__ == '__main__':
app.run(debug=True)
Approach 2: use Sijax (updates div, but how to access form inputs?)
form_test_sijax.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Testpage with sijax</title>
<script type="text/javascript" src="/static/js/sijax/sijax.js"></script>
<script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script>
</head>
<body>
<form method="post">
A = <input type="number" name="input_A">
B = <input type="number" name="input_B">
<button type="button" onclick="Sijax.request('submit_form');">calc</button>
</form>
<div id="destination_div">A + B = unknown</div>
</body>
</html>
app_sijax.py
from flask import Flask, render_template, g
import flask_sijax
import os
app = Flask(__name__)
# init sijax
app.config["SIJAX_STATIC_PATH"] = os.path.join('.', os.path.dirname(__file__), 'static/js/sijax/')
app.config["SIJAX_JSON_URI"] = '/static/js/sijax/json2.js'
flask_sijax.Sijax(app)
def submit_form_handler(obj_response):
A = 5 # how do get to the values entered in the form?
B = 3
sum = A + B
obj_response.html("#destination_div", "A + B = " + str(sum))
#flask_sijax.route(app, "/")
def show_home():
result = 'unknown'
if g.sijax.is_sijax_request:
g.sijax.register_callback('submit_form', submit_form_handler)
return g.sijax.process_request()
return render_template("form_test_sijax.html")
if __name__ == '__main__':
app.run(debug=True)
You can use ajax with jquery to dynamically update the page with the computed result without having to refresh the page:
In the html file:
<html>
<header>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
</header>
<body>
<div class='wrapper'>
A = <input type="number" id="input_A">
B = <input type="number" id="input_B">
<button class='get_result'>Calculate</button>
<div class='result'></div>
</div>
</body>
<script>
$(document).ready(function(){
$('.wrapper').on('click', '.get_result', function(){
var val1 = $("#input_A").val();
var val2 = $("#input_B").val();
$.ajax({
url: "/calculate_result",
type: "get",
data: {val1: val1, val2:val2},
success: function(response) {
$(".result").html('<p>'+response.result.toString()+'</p>');
},
});
});
});
</script>
</html>
Then, in the main app file, create the route to calculate the final result:
#app.route('/calculate_result')
def calculate_result():
a = int(flask.request.args.get('val1'))
b = int(flask.request.args.get('val2'))
return flask.jsonify({"result":a+b})

Sijax obj_response does not alert or modify any content in flask?

My form submits data through a sijax request and to acknowledge the submission I use obj_response. I tried both obj_response.alert() as well as obj_response.html() but nothing worked
My code:
from flask import Flask, render_template, request, flash, g, redirect, url_for
from flask_sqlalchemy import SQLAlchemy
import flask_sijax
import os
app = Flask(__name__)
app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///Login.sqlite3"
path = os.path.join('.', os.path.dirname(__file__), 'static/js/sijax1/')
app.secret_key = 'super secret key'
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SIJAX_STATIC_PATH'] = path
app.config['SIJAX_JSON_URI'] = 'static/js/sijax/json2.js'
db = SQLAlchemy(app)
flask_sijax.Sijax(app)
class Signup(db.Model):
ID = db.Column("ID", db.String(10), primary_key=True)
Fname = db.Column(db.String(20))
LName = db.Column(db.String(20))
Password = db.Column(db.String(20))
def __init__(self, id, fname, lname, password):
self.ID = id
self.Fname = fname
self.LName = lname
self.Password = password
#flask_sijax.route(app, '/signup')
def home():
def caller(obj_response, values):
newuser = Signup(values['ID'], values['fname'], values['lname'], values['Password'])
db.session.add(newuser)
db.session.commit()
obj_response.html("#result", "Successfully signed up")
if g.sijax.is_sijax_request:
g.sijax.register_callback('call', caller)
return g.sijax.process_request()
return render_template("first.html")
#app.route("/success", methods=['POST', 'GET'])
def success():
records = db.session.query(Signup).all()
return render_template("second.html", records=records)
if __name__ == "__main__":
db.create_all()
app.run(host="127.0.0.1", port=2908, debug=True, threaded=True)
My HTML file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Sign Up</title>
<script type="text/javascript" src="{{url_for('static',filename='Signup.js')}}"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script type="text/javascript" src="{{url_for('static', filename='js/sijax/sijax.js')}}"></script>
<script type="text/javascript">{ {g.sijax.get_js()|safe }}</script>
<link rel="stylesheet" href="{{url_for('static', filename='styles/firstcss.css')}}">
</head>
<body style = "font-family: Lato">
<div style="padding-left: 5%;padding-top:0.2%;padding-bottom: 0px;height: 4%;width: 100%;background-color: #11557C;margin-left: 0px;margin-top: 0px;">
<h2>Welcome to my site</h2><br>
</div>
<div style="margin-left: 70%" width="100%">
<form method="post" action="http://127.0.0.1:2908/success">
<input type="submit" style="position: relative;margin-top: 5%;margin-left:20%" value="View Logs">
</form>
</div>
<div style="width:80%">
<form name="form1" id="form1" method="post" style="padding-top: 1%"><!--action = "http://127.0.0.1:2908/success"!-->
<label id="head" style="font-size: 20px;padding-bottom: 1%;">Sign Up</label><br>
<label id="user" style="font-size: 16px;margin-top: 5%;">Username</label><br>
<input type="text" name = "ID" placeholder = "Username" style = "padding-left: 0.2%;"><br><br>
<label style="font-size: 16px">First name</label><br>
<input type="text" name = "fname" id="fname" placeholder = "First name" style = "padding-left: 0.2%"><br><br>
<label style="font-size: 16px">Last name</label><br>
<input type="text" name = "lname" placeholder = "Last name" style = "padding-left: 0.2%"><br><br>
<label style="font-size: 16px">Password</label><br>
<input type = "password" name = "Password" placeholder = "Password" style = "padding-left: 0.2%"><br><br><br>
<input type = "submit" onclick="return validate()" value = "Sign up" style="width:50%;height: 40px;margin-left: 12%;background-color: #11557C;color: black">
</form>
</div>
<h3 id="result" >RESULT</h3>
</body>
</html>
I noticed Sijax stopped working when using a jQuery version higher then 1.5.1
So try replacing:
https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js
With:
https://ajax.googleapis.com/ajax/libs/jquery/1.5.1/jquery.min.js
But I did not find any other confirmation from other developers or forums on this point, just my own.

Categories

Resources