action after button click in scroll menu in html with using Flask - python

I have array of two elements in flask:
from flask import Flask, render_template
import psycopg2
import numpy as np
app = Flask(__name__)
d = [10,12,16,17]
#app.route('/about')
def about():
return render_template('about.html', d=d, length=len(d))
if __name__ == '__main__':
app.run()
And also I have Vertical Scroll Menu in html:
<h1>Vertical Scroll Menu</h1>
<div class="vertical-menu">
change number
{% for i in range(length) %}
select number{{d[i]}}
{% endfor %}
</div>
<input type="text" name="name" required="required">
I need to insert number in array into output form after href clicking.How should I solve my problem?

Demo HTML
<form action="{{url_for('process_number')}}" method="POST">
<select name="number">
{% for i in d %}
<option value="{{d[i]}}">{{d[i]}}</option>
{% endfor %}
</select>
<input type="submit"/>
</form>
Flask function
#app.route('/process-number', methods=['GET', 'POST'])
def process_number():
if request.method == 'POST':
selected_number = request.form['number']
# do what you want

Related

POST Method not allowed for a simple lookup webpage

I have a simple page with a data entry field and a click button, this will run the API to retrieve the coin data
running the code in a python terminal return with success, but when I try to add it to flask and use the webpage, I get the error 405 method not allowed for the POST.
This is the main python/flask file:
crypto.py
# template libraries
from flask import render_template,url_for,flash,request,redirect,Blueprint
# Coingecko API library
from pycoingecko import CoinGeckoAPI
crypto_simulator = Blueprint('crypto_simulator',__name__)
#crypto_simulator.route('/crypto_simulator', methods=['GET','POST'])
#login_required
def crypto_insert():
if request.form.get("ident") == "formCrypto":
print('Hello')
cg = CoinGeckoAPI()
#crypto_token = request.form.get('crypto_name_html', '')
crypto_token = 'bitcoin'
crypto_currency = 'usd'
response = cg.get_price(ids=crypto_token,
vs_currencies='usd',
include_market_cap='true',
include_24hr_vol='true',
include_24hr_change='true',
include_last_updated_at='true')
crypto_result = response.get(crypto_token,'')
print(crypto_result[crypto_currency])
return render_template('crypto_simulator.html',
formCryptoSimulation=form,
crypto_token=crypto_token,
crypto_currency=crypto_currency,
crypto_result=crypto_result
)
This is the Blueprint routing file:
core.py
# crypto section
#core.route('/crypto_simulator')
def crypto_simulator():
return render_template('crypto_simulator.html')
This is the Flask/Bootstrap front-end:
crypto_simulator.html
{% extends "base.html" %}
{% block content %}
<!-- Simulation Code Start -->
<div class="forms">
<div class="formCrypto">
<form method="post" action="{{ url_for('core.crypto_simulator') }}">
<div class="container">
<div class="row g-3">
<div class="col-sm-3">
<label class="form-label"><b>Crypto Name:</b></label>
<input type="text" class="form-control" name="crypto_name_html" placeholder="Enter Crypto Name" required>
</div>
</div>
</div>
<br>
<div class="d-grid gap-2 d-md-flex justify-content-md-start">
<button id="btn" type="submit" class="btn btn-info">Check Token!</button>
</div>
<input type=hidden name="ident" value="formCrypto">
</form>
<br>
<p>Token: <b>{{crypto_token}}</b>
<p>Price: <b>{{crypto_result}}</b>
</div>
</div>
{% endblock %}
I checked for misspelled lines and anything related but still stuck into how to fix it...
Your form has this:
<form method="post" action="{{ url_for('core.crypto_simulator') }}">
So you are calling the function crypto_simulator in blueprint core:
#core.route('/crypto_simulator')
def crypto_simulator():
return render_template('crypto_simulator.html')
Note that your form does a POST request, so you very logically have to enable the POST method on the function being called like this:
#core.route('/crypto_simulator', methods=['GET','POST'])

Flask Application Showing 404 on Post

This is my first attempt at deploying a machine learning application and also my first time using flask. Essentially the user will fill out a form on an html page and the input from the form will be used as input to the machine learning model which is saved in a pickle file, model.pkl in the code below. I am running into one snag that I can't seem to break past..
Every time I submit from index.html and post to result.html I'm receiving a 404 error.
script.py:
#importing libraries
import os
import numpy as np
import flask
import pickle
from flask import Flask, render_template, request
app=Flask(__name__)
#app.route('/')
#app.route('/index')
def index():
return flask.render_template('index.html')
def ValuePredictor(to_predict_list):
to_predict = np.array(to_predict_list).reshape(1,12)
loaded_model = pickle.load(open("model.pkl","rb"))
result = loaded_model.predict(to_predict)
return result[0]
#app.route('/result',methods = ['POST'])
def result():
if request.method == 'POST':
to_predict_list = request.form.to_dict()
to_predict_list=list(to_predict_list.values())
to_predict_list = list(map(int, to_predict_list))
result = ValuePredictor(to_predict_list)
if int(result)==1:
prediction='Income more than 50K'
else:
prediction='Income less that 50K'
return render_template("result.html",prediction=prediction)
index.html:
<html>
<body>
<h3>Income Prediction Form</h3>
<div>
<form action="/result.html" method="POST">
<label for="age">Age</label>
<input type="text" id="age" name="age">
<br>
<label for="edu">Education</label>
<select id="edu" name="edu">
<option value="0">High School</option>
<option value="1">College Degree</option>
</select>
<br>
<label for="martial_stat">Marital Status</label>
<select id="martial_stat" name="martial_stat">
<option value="0">not married</option>
<option value="1">married</option>
</select>
<br>
<label for="gender">Gender</label>
<select id="gender" name="gender">
<option value="0">Female</option>
<option value="1">Male</option>
</select>
<br>
<input type="submit" value="Submit">
</form>
</div>
</body>
</html>
result.html:
<html>
<body>
<h1> {{ prediction }}</h1>
</body>
</html>
I can't seem to figure this out. My code never seems to reach the first line in the result() function. As soon as I submit from index.html http://127.0.0.1:5000/result.html throws a 404 error. Any suggestions?
The error is very simple here, the action property in index.html should just be
<form action="/result" method="POST">
instead of
<form action="/result.html" method="POST">
You want to use /result to go through your flask function. Hope this helps!
You are posting to the endpoint /result.html:
<form action="/result.html" method="POST">
... but your route in flask is defined as /result (with no .html):
#app.route('/result',methods = ['POST'])
def result():
...
These two need to match, so consider changing the route to result.html.
Instead of <form action="/result.html" method="POST">
Can Use <form action="{{ url_for('result') }}" method="POST">

Keep Upload Data for Analyses in Flask Session

I am very much struggling with a concept and hope someone can offer a code implementation suggestion. I have the following route embedded within my flask app. After working on this for a few days I think I now see the nature of the issue. I have modified my code based on suggestion below in comments.
In the web app now, the names of the data frame columns populate a drop down menu and the user can choose one of those variables and click "Show". That variable name then prints to the screen just so I know my POST from the form is communicating with my function in the flask app.
What I would like to do is create a temp version of the file uploaded so that it exists as long as the web session is open (or is overwritten if a new file upload occurs). Then, the user chooses a variable from the drop down menu and the mean of that variable is computed (that part is commented out in the code below for now but you can see what I have tried).
If the user reads in a new file, then the same process would occur on that new file.
Thanks for any suggestions or supports.
from flask import Flask, render_template, request
import numpy as np
from scipy.stats import binom
from scipy.optimize import minimize
from scipy.stats import norm
from scipy import optimize
from pyodbc import connect
import pandas as pd
import os
import tempfile
app = Flask(__name__)
#app.route('/dataTools', methods=['POST', 'GET'])
def data_tools_upload():
tempfile_path = tempfile.NamedTemporaryFile().name
if request.files:
df = pd.read_csv(request.files.get('file'))
#tempfile_path = tempfile.NamedTemporaryFile().name
df.to_csv(tempfile_path)
if os.path.exists(tempfile_path):
orig_df = pd.read_csv(tempfile_path)
vars = list(orig_df.columns)
var2use = request.form.get("var2use")
#indx = vars.index(var2use)
#df[vars[indx]].mean()
mean = orig_df[vars[4]].mean()
dims = orig_df.shape
message = 'You have data! There are %s rows and %s columns and the variable %s has mean %s' % (dims[0],dims[1],vars[4],round(mean,3))
table = orig_df.head(10).to_html(classes='data', header = "true")
return render_template('upload.html', tables = [table], message = message, vars = vars, var_name = var2use)
var2use = request.form.get("var2use")
return render_template('upload.html', var_name = var2use, message = "What happened?")
if __name__ == '__main__':
app.run(debug=True)
And then the following HTML bit (upload.html):
{% extends "layout.html" %}
{% block body %}
<h3> Read in a data file </h3>
<br>
<form method=post enctype=multipart/form-data>
<input type=file name=file class = "btn btn-outline-secondary">
<input type=submit value=Upload class = "btn btn-outline-secondary">
</form>
<br>
<form class="form-inline" action = "{{url_for('data_tools_upload')}}" method = "POST">
<select type = "text" name="var2use" class="custom-select mr-sm-1">
{% for var in vars %}
<option value= "{{ var }}" SELECTED>{{ var }}</option>"
{% endfor %}
</select>
<button class = "btn btn-primary"> Show </button>
</form>
<center>
<h1>
{{message}}
{{name}}
</h1>
<br>
<small>
{% for table in tables %}
{{ table|safe }}
{% endfor %}
{% endblock %}
</small>
</center>
you need to save file to work with it (the code works perfectly in my app):
f = request.files['file']
tmp_filename = '/tmp/my_tmp_file.csv'
f.save(tmp_filename)
pd.read_csv(tmp_filename)
Here is the detailed documentation on Flask file uploads:
https://flask.palletsprojects.com/en/1.1.x/patterns/fileuploads/
Full example for your case is below. I think you might have problems with the following three items:
Uploading the file because of form enctype (should be "multipart/form-data")
Uploading because of file size (try my sample)
Processing the form with empty file overwriting yours (see my example for "csv_file_uploaded")
Python (csv_test.py):
from flask import Flask, render_template, request
import pandas as pd
import os
app = Flask(__name__, static_url_path='')
#app.route('/', methods=['GET', 'POST'])
def index():
data = {}
tmp_filename = '/tmp/csv_test.csv'
if request.files:
csv_file_uploaded = request.files.get('file')
if csv_file_uploaded:
f = request.files['file']
f.save(tmp_filename)
if os.path.exists(tmp_filename):
df = pd.read_csv(tmp_filename)
data['columns'] = ', '.join(df.columns)
col_selected = request.form.get('col_selected')
print(col_selected)
data['col_selected'] = col_selected
if col_selected:
mean = df.get(col_selected).mean()
data['mean'] = mean
return render_template('csv_test.tpl', data=data)
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0')
Flask template (csv_test.tpl):
<html><head><title>CSV TEST</title></head>
<body><h1>CSV TEST</h1>
{% if data %}
<div>Columns of the uploaded file: <strong>{{ data.columns }}</strong></div>
<div>Selected column: <strong>{{ data.col_selected }}</strong></div>
<div>Mean of the selected = <strong>{{ data.mean }}</strong></div>
{% endif %}
<fieldset>
<form enctype="multipart/form-data" action="" method="post">
<h2>Provide some CSV with first column in numbers and/or column name</h2>
<div>File{% if data.columns %} (UPLOADED){% endif %}: <input id="file" type="file" name="file"/></div>
<div>Column: <input id="col_selected" type="text" name="col_selected" value="{{ data.col_selected }}"/></div>
<div><input id="submit" type="submit" value="SUBMIT"/></div>
</form>
</fieldset>
</body></html>
CSV file (123.csv) - use it to test the form:
col1,col2
1,2
2,3
3,4
5,6

how to create a dynamic url from form using flask

I have a form on my home page that is generated from a list of folders on disk. I can't figure out how to route to the next page and add a dynamic url. So that the url reads http://127.0.0.1:5000/projects/
(http://127.0.0.1:5000/projects/banana)
(http://127.0.0.1:5000/projects/apple)
#app.route("/")
def home():
return render_template("home.html", list_projects=list_projects)
#app.route('/', methods=['POST', 'GET'])
def project_select_form():
project_select = request.form['project']
return redirect(url_for("project_page"), project=project_select)
#app.route('/projects/<project>', methods=['POST', 'GET'])
def project_page(project):
return render_template("project_selected.html", project=project)
if __name__ == "__main__":
html
<form method = "POST">
<select id="project" name="project">
{% for x in list_projects %}
<option value="{{ x }}">{{ x }}</option>
{% endfor %}
</select>
<input name="text" type="submit">
</form>
All you need to do is, add a JavaScript/jQuery function that will call the URL.
<form method="GET">
<select id="project" name="project">
<option value="a1">a1</option>
<option value="b1">b1</option>
</select>
<input type="button" value="Submit" onclick="myFunction()">
</form>
With this slight modification in your form, you can now have a function like this:
<script>
function myFunction() {
var e = document.getElementById("project");
var list_project = e.options[e.selectedIndex].value;
var theUrl = "http://127.0.0.1:5000/project/".concat(list_project);
window.location.replace(theUrl);
}
</script>
This simply calls the URL, which in turn renders the project_selected.html.
Hope this helps. Good luck.
The answer was to add an if statement to the form. Otherwise it errors out
#app.route("/", methods=['POST', 'GET'])
def home():
if request.form:
project_select = request.form['project']
return redirect(url_for("project_page", project=project_select))
else:
return render_template("home.html", list_projects=list_projects)

Flask and Python how to make search engine for data from mysql database

I want to make some kind of search engine for student's information by entering their first name in html input field, but I have some troubles with my code. I am using Flask with Python though.
Here is my project.py code:
#app.route('/search', methods=['GET', 'POST'])
def search():
if request.method == "POST":
db = MySQLdb.connect(user="root", passwd="", db="cs324", host="127.0.0.1")
c=db.cursor()
c.executemany('''select * from student where name = %s''', request.form['search'])
for r in c.fetchall():
print r[0],r[1],r[2]
return redirect(url_for('search'))
return render_template('search.html')
Here is my search.html code:
{% extends "hello.html" %}
{% block content %}
<div class="search">
<form action="" method=post>
<input type=text name=search value="{{ request.form.search}}"></br>
<div class="actions"><input type=submit value="Search"></div>
</form>
</div>
{% for message in get_flashed_messages() %}
<div class=flash>
{{ message }}
</div>
{% endfor %}
{% endblock %}
When I hit Search button nothing happens, I checked database it has some data in it so it is not empty, I can't find where am I making a mistake, please help?
Make sure, action point to proper url
I think you render the form with wrong action for submitting the form.
Your version is using action="" and I guess, it shall be action="/search"
So your template shall be changed like:
{% extends "hello.html" %}
{% block content %}
<div class="search">
<form action="/search" method=post>
<input type=text name=search value="{{ request.form.search}}"></br>
<div class="actions"><input type=submit value="Search"></div>
</form>
</div>
{% for message in get_flashed_messages() %}
<div class=flash>
{{ message }}
</div>
{% endfor %}
{% endblock %}
Do not redirect out of your result
Your existing code is processing POST, but within first loop it ends up returning with redirect
#app.route('/search', methods=['GET', 'POST'])
def search():
if request.method == "POST":
db = MySQLdb.connect(user="root", passwd="", db="cs324", host="127.0.0.1")
c=db.cursor()
c.executemany('''select * from student where name = %s''', request.form['search'])
for r in c.fetchall():
print r[0],r[1],r[2]
return redirect(url_for('search')) # <- Here you jump away from whatever result you create
return render_template('search.html')
Do render your template for final report
Your code does not show in POST branch any attempt to render what you have found in the database.
Instead of print r[0], r[1]... you shall call render_template()
Something like this
#app.route('/search', methods=['GET', 'POST'])
def search():
if request.method == "POST":
db = MySQLdb.connect(user="root", passwd="", db="cs324", host="127.0.0.1")
c=db.cursor()
c.executemany('''select * from student where name = %s''', request.form['search'])
return render_template("results.html", records=c.fetchall())
return render_template('search.html')

Categories

Resources