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.
Related
My goal is to have a Flask app who let the user put a csv file and the app return an specific output.
Here's the output I want, let me show you how I done it in jupyter notebook :
for i in df['variable1'].unique():
data = df[(df['variable1'] == i)]
data['list'] = data['comms_clean'].apply(lambda x: str(x).split())
top = Counter([item for sublist in data['list'] for item in sublist])
mostcommon = pd.DataFrame(top.most_common(3))
mostcommon.columns = ['Common Word', 'Count']
print()
print('For the classe "{0}" who appears {1} time, here is the 3 most frequent word: '.format(i, data.shape[0]))
print()
print(mostcommon.head(3))
print()
And here's the result :
For the classe "classe1" who appears 389 time, here is the 3 most frequent word:
Common Word Count
0 word10 267
1 word20 149
2 word30 46
For the classe "classe1" who appears 657 time, here is the 3 most frequent word:
Common Word Count
0 word40 234
1 word50 89
2 word60 34
For the classe "classe3" who appears 250 time, here is the 3 most frequent word:
Common Word Count
0 word70 90
1 word80 30
2 word90 19
...
But I cannot figure it out how to transpose this into Flask.
Here's my app.py :
from flask import Flask, render_template, request
from werkzeug.utils import secure_filename
import os
import pandas as pd
ALLOWED_EXTENSIONS = {'csv', 'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
UPLOAD_FOLDER = 'uploads/'
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and filename.rsplit('.',1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/', methods=['GET','POST'])
def upload_file(filename=None,column=None, data=None):
if request.method == 'GET':
render_template('index.html')
if request.method == 'POST':
if 'file' not in request.files:
flash("No file part")
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash("No selected file")
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(file_path)
df = pd.read_csv(file_path, delimiter = ';')
column = list(df)
data = [list(df[d]) for d in column]
df_head = df.head()
return render_template('index.html', data=data, tables=[df_head.to_html(classes='data')], titles=df.columns.values)
return render_template('index.html')
if __name__ == '__main__':
app.run(debug=True)
And here's my index.html :
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Upload File</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" type="text/css" media="screen" href="main.css" />
<script src="main.js"></script>
</head>
<body>
{% if data %}
{% for table in tables %}
{{titles[loop.index]}}
{{ table|safe }}
{% endfor %}
{% endif %}
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
</body>
</html>
But this app give me the head() of the csv file uploaded, the specific output I want is way harder to implement so if you could help me, it would be awesome.
I think I need to create a dataframe with my most frequent word because Flask seems to need a dataframe but I'm not entirely sure.
Any suggestions ?
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:
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("&", "&")
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">
I am working on Malicious Webpage Detection using logistic regression and have used a dataset from kaggle. Using flask and html i want to predict whether the url is good or bad.
this is the code snippet in app.py
if request.method=='POST':
comment=request.form['comment']
X_predict1=[comment]
predict1 = vectorizer.transform(X_predict1)
New_predict1 = logit.predict(predict1)
new = New_predict1.tolist()
new1 = " ".join(str(x) for x in new)
return render_template('result.html',prediction=new1)
this code i have written in result.html
{% if prediction == 1%}
<h2 style="color:red;">Bad</h2>
{% elif prediction == 0%}
<h2 style="color:blue;">Good</h2>
{% endif %}
Why the results (Bad/Good) are not being displayed for this code?
I assume in app.py:
New_predict1.tolist() returns a list.
" ".join(str(x) for x in new) returns a concatenated string value.
In result.html:
prediction == 1 or prediction == 0 compares the value of prediction to integer. But from app.py you are sending a concatenated string value. So, this Bad or Good will not be shown in template.
You need to use String comparison like: prediction == "some constant"
I reproduced your scenario:
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/', methods = ['GET', 'POST'])
def home():
if request.method == "POST":
comment=request.form.get('comment')
X_predict1=[comment]
# Do some operations
#predict1 = vectorizer.transform(X_predict1)
#New_predict1 = logit.predict(predict1)
#new = New_predict1.tolist()
#new1 = " ".join(str(x) for x in new)
# Dummy list
new = [1, 2, 3]
# " ".join() returns a string
new1 = " ".join(str(x) for x in new)
return render_template('result.html', prediction=new1)
return render_template('result.html')
if __name__ == "__main__":
app.run(debug=True)
result.html:
<html>
<head>
<title>Home</title>
</head>
<body>
<form action="/" method="post">
Comment:
<input type="text" name="comment"/>
<input type="submit" value="Submit">
</form>
<h3>Prediction Result</h3>
{% if prediction == 1 %}
<h2 style="color:red;">Bad</h2>
{% elif prediction == 0 %}
<h2 style="color:blue;">Good</h2>
{% else %}
<h2 style="color:black;">{{prediction}}</h2>
{% endif %}
</body>
</html>
Output:
As you can see the else block is triggered in the template as both if and elif block is skipped.
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')