response.form.get getting No Values in flask python application - python

I am new to flask application. I am trying to loop over input of webapp. Based on which i want to show the result on web app. Html template is fine, UDF is also fine only key_from_web is not fetching any value so result is also blank list.
Html:
<!doctype html>
<html>
<head>
<title>superman </title>
</head>
<body> Enter the Registration Number !</body>
<div class="login">
<form action="{{url_for('details')}}">
<input type="text" name="Siret Number" placeholder="siret if you are in France" required="required" />
<button type="submit" class="btn btn-primary btn-block btn-large"> Details </button>
</form>
</div>
<br>
{{ prediction_text }}
</html>
Python:
app = Flask(__name__)
#app.route('/')
def home():
return render_template("sample.html")
#app.route('/details',methods=['Get','POST'])
def details():
d = {'col1': [1,1,2], 'col2': [3, 4, 5]}
df = pd.DataFrame(data=d)
df_dict= {str(k): v.to_json(orient= 'records') for k , v in df.groupby('col1')}
# value entered on web app
key_from_web = request.form.get("Siret Number")
result = []
for key_,val_ in df_dict.items():
"""when key_ is entered it should show json output of MATCHED Key_'s val_"""
if key_ == key_from_web:
result.append(val_)
return render_template("sample.html", prediction_text = f"Company details are : {result}")
#call main fun
if __name__ == "__main__":
app.run(debug=True)
Expected Output:
If user enter 1 it should display respective value [{"col1":1,"col2":3},{"col1":1,"col2":4}]

Related

How do we handle empty forms in Flask?

I've written an app that reads data from a csv file and displays the student id and course id and their marks. I am having difficulty in handling situations when no buttons are selected and no text written and submit is pressed or when something is written in text field and no buttons are selected and submit is pressed.
Flask should render error.html in both of the above situations but I am getting a bad request error.
Please see the below code
from flask import render_template
from flask import Flask, request
from matplotlib import pyplot as plt
def read_csv():# Function to read csv
student_dic = {}
courses = []
file = open("./data.csv")
count = 0
a = file.readlines()
for line in a:
r = line.split(",")
if r[1] not in courses:
courses.append(r[1].strip())
r[2] = r[2].rstrip()
if count == 0:
count = count + 1
continue
if (r[0]) in student_dic:
k = {}
k[(r[1].strip())] = int(r[2])
student_dic[(r[0])].update(k)
else:
student_dic[(r[0])] = {(r[1].strip()): int(r[2])}
return ([student_dic, courses])
def plot_hist(marks_list):# Function to plot
plt.hist(marks_list)
plt.savefig("./static/hist.png")
plt.close()
app = Flask(__name__)
#app.route("/", methods=['GET', 'POST'])
def index():
if request.method == "GET":
return render_template("index.html")
elif request.method == "POST":
option = request.form["ID"]
print("here",option)
dic, courses = read_csv()
if option == "student_id":
user_input = (request.form["id_value"])
if user_input == '':
return render_template("error.html")
else:
if user_input in dic:
student_id_dic = dic[user_input]
total_marks = sum(student_id_dic.values())
return render_template("student_details.html", course_id_data=student_id_dic,
student_id_data=user_input,
total_marks_data=total_marks)
else:
return render_template("error.html")
elif option == "course_id":
user_input_course = request.form["id_value"]
if user_input_course == '':
return render_template("error.html")
else:
if user_input_course in courses:
ct = 0
max_marks = -1
total = 0
mark_list = []
h = 0
for student_id in dic:
for key, value in dic[student_id].items():
if key == user_input_course:
mark_list.append(value)
ct = ct + 1
total = total + value
if value > max_marks:
max_marks = value
plot_hist(mark_list)
return render_template("course_details.html", average_marks=(total / ct), maximum_marks=max_marks,
img='./static/hist.png')
else:
return render_template("error.html")
return render_template("error.html")
return render_template("error.html")
if __name__ == "__main__":
app.run(host='0.0.0.0')
app.debug = True
Here is the index html file
<!DOCTYPE html>
<html lang="en">
<head>
<title>Enter Details</title>
</head>
<body>
<div class="main">
<h1>Enter the details</h1>
<form method="POST" action="/" id = "data-form">
<input type="radio" name="ID" value="student_id" />
<label>Student ID</label>
<input type="radio" name="ID" value="course_id" />
<label>Course ID</label>
<input type="text" name="id_value" />
<input type="submit" value="Submit" />
</form>
</div>
</body>
</html>
This is the error html
<!DOCTYPE html>
<html lang="en">
<head>
<title>Something Went Wrong</title>
</head>
<body>
<div class="main">
<h1>Wrong Inputs</h1>
<p> Something went wrong </p>
<br>
Go Back
</div>
</body>
</html>
This would probably be better handled using form validators, rather than adding logic in the route and custom error pages. If you don't want users to submit the form without certain information, just make it impossible to do (using validators). This will also be a better user experience, since they won't have to click "Go Back" on the error page.
You can use built-in validators, such as DataRequired, and you can also write custom validation functions.

Unable to retrieve the values in flask

I have used pymongo and retrieved all the values in collection which is stored in mongo atlas and I wanted only lat so I have stored all the lat like this.
a_float = [a['Lat'] for a in results1]
where results1=collection1.find({}) and collection1 = db["Latitude"]
Now in flask I'm trying to compare the input lat with mongo lat. Every time else condition is being executed. My flask code is as follows
#app.route("/")
def hello():
return render_template('home.html')
#app.route("/echo", methods=['POST'])
def echo():
a=request.form['lat']
b=request.form['long']
if a in a_float:
msg = "present"
return render_template('root.html', msg=msg, a=a, b=b)
else:
msg = "absent"
return render_template('root.html', msg=msg, a=a, b=b)
My HTML code home.html
<!DOCTYPE html>
<head>
</head>
<body>
<form method="POST" action="/echo">
Enter the lat<input type="text" name = 'lat' >
Enter the long<input type="text" name = 'long' >
<input type="submit" value="submit">
</form>
</body>
</html>
root.html
<!DOCTYPE html>
<head>
</head>
<form>
</form>
<body>
{{ msg }}
Lat : {{a}}
Long : {{b}}
</body>
</html>
Are you sure your comparison is the same type?
Try converting before comparison if the list element has float values:
a = float(request.form['long'])
Or
a = request.form.get('long', type=float)
See more about this way here

Flask - Multi user access with OOP

I created an app with flask but I'm having a problem with multi-user access bcs of the global variables. Whenever I run the script (it might take minutes) and someone else is trying to access the page and run a script there too a collision appear and data by both users mix.
I truly understand that I should be using OOP in this case, but I'm not able to replicate the OOP usage for this app (yes, I'm an OOP beginner ). Can someone please give me a hint or a little bit of code about OOP for this case?
Much appreciated.
Python:
from flask import Flask, render_template, url_for, request, redirect, Response
from datetime import datetime
import time
import pandas as pd
import re
import os
app = Flask(__name__)
#app.route('/', methods=['POST', 'GET'])
def index():
if request.method == 'POST':
start_date = request.form["Start_date"]
end_date = request.form["End_date"]
dates = pd.period_range(start=start_date, end=end_date, freq='D')
global s_date
global f_date
s_date = dates[0]
f_date = dates[-1]
print(s_date, f_date)
query = request.form["query"].strip()
splitted = query.split("\r\n")
global fiii
fiii = pd.DataFrame()
for x in splitted:
print(x)
for date in dates:
print(date)
directory = '/home/USER/Parquets/{}/{:02d}/{:02d}/'.format(date.year, date.month, date.day)
for filename in os.listdir(directory):
if filename.endswith(".parquet"):
df = pd.read_parquet(directory)
df.set_index("query", inplace=True)
if request.form.get('lowercase') == "on":
df.index = df.index.str.casefold()
if request.form.get('sensitive') == "on":
fiii = fiii.append(df.filter(regex=re.compile(x), axis=0))
else:
fiii = fiii.append(df.filter(regex=re.compile(x, re.IGNORECASE), axis=0))
fiii = fiii.groupby(['query'])["total"].sum().sort_values(ascending=False)
if request.form.get('csv') == "on":
return redirect("/getCSV")
else:
pass
# return render_template("index.html")
return fiii.to_frame().to_html(table_id="table")
else:
return render_template("index.html")
#app.route("/getCSV")
def getPlotCSV():
return Response(
fiii.to_csv(encoding="UTF-8", sep="\t", header=True),
mimetype="text/csv",
headers={"Content-disposition":
f"attachment; filename={s_date}-{f_date}.csv"})
if __name__ == "__main__":
app.run(debug=True,port=4444)
HTML:
<html lang="en"><head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/mate rialize/1.0.0/css/materialize.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js /materialize.min.js"></script>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel ="stylesheet">
</head>
<body>
<div class="container">
<div class="row">
<form class="col s6 offset-s3" action="/" method="POST">
<div class="valign-wrapper col s12">
<h3 class="col s6">Query master</h3>
<div class="right-align input-field col s6">
<button class="btn btn-large btn-floating waves- effect waves-light" type="submit" name="action">
<i class="material-icons right">send</i>
</button>
</div>
</div>
<div class="input-field col s12">
<input type="text" id="date-start" class="datepicker " name="Start_date">
<label for="date-start">Start Date</label>
</div>
<div class="input-field col s12">
<input type="text" id="date-end" class="datepicker" name="End_date">
<label for="date-end">End Date</label>
</div>
<label class="input-field col s12">
<input type="checkbox" name="lowercase" />
<span>Lowercase queries</span>
</label>
<label class="input-field col s12">
<input type="checkbox" name="sensitive" />
<span>Case sensitive</span>
</label>
<label class="input-field col s12">
<input type="checkbox" name="csv" />
<span>CSV export (Funkční pouze csv export)</span>
</label>
<div class="input-field col s12">
<textarea id="textarea1" name="query" class="materia lize-textarea"></textarea>
<label for="textarea1">Queries (RegEx supported)</la bel>
</div>
</form>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
var elems = document.querySelectorAll('.datepicker');
var instances = M.Datepicker.init(elems, {
format: 'm/d/yyyy',
});
});
</script>
</div>
</body>
</html>
Your problem has absolutely nothing to do with OO - it's only the result of using gobal variables.
Your flask server process will serve all incoming requests, one after the other. So what happens in a multi-user scenario is:
1/ user A posts to index. This assigns values to your globals s_date, f_date and fills.
2/ user A is redirected to getCSV
3/ in the meantime, user B posts to index. This rebinds your globals s_date, f_date and fills to new values
4/ user A's browser has followed the redirection, and renders the fill of user B.
The solution is quite simple: do NOT use global state for per-user data persistance - you want either a user session for short-lived session data and/or a RDBMS for long-lived user data.

Extracting a list of lists from input box and checkbox values in flask

This is the my index.html
<!DOCTYPE html>
<script>
function add_field()
{
var total_text=document.getElementsByClassName("input_text");
total_text=total_text.length+1;
field_div = document.getElementById("field_div");
new_input = "<li id='input_text"+total_text+
"_wrapper'><input type='text' class='input_text' name='input_text[]' id='input_text"+
total_text+"' placeholder='Enter Text'>"+
"<label><input name='input_text"+total_text+"' id='input_text[]' type='radio' value='1'>1</label>"+
"<label><input name='input_text"+total_text+"' type='radio' id='input_text[]' value='2'>2</label>"+
"</li>";
field_div.insertAdjacentHTML('beforeend',new_input);
}
function remove_field()
{
var total_text=document.getElementsByClassName("input_text");
document.getElementById("input_text"+total_text.length+"_wrapper").remove();
}
</script>
{% extends "bootstrap/base.html" %}
{% block content %}
<div class = "container">
<h1>Give the words</h1>
<form action='/results' method="post">
<div id="wrapper">
<input type="button" value="Add TextBox" onclick="add_field();">
<input type="button" value="Remove TextBox" onclick="remove_field();">
<ol id="field_div">
</ol>
</div>
<input type='submit' value='Select'>
</form>
</div>
{% endblock %}
My views.py is as follows:
from flask import render_template, request, url_for
from app import app
from .translit import *
#app.route('/')
def search():
return render_template('index.html')
#app.route('/results', methods = ['GET', 'POST'])
def results():
if request.method == 'GET':
return redirect(url_for('/'))
else:
values = getperm(request.form.getlist('input_text[]'))
print(request.form.getlist('input_text[]'))
return render_template('results.html',
values = values)
Right now, I can extract the input from all the input texts as a list?
How do I get the values form each <li> as a list thereby creating a list of lists?
As an example,
if i type
a 1
b 2
I should be able to extract the result as [[a,1],[b,2]]
We should manipulate the value attribute of checkbox.
Added checkbox with each textbox.
app.py:
from flask import Flask, render_template, url_for, request
app = Flask(__name__)
#app.route('/')
def search():
return render_template('dynamic_input.html')
#app.route('/results', methods = ['GET', 'POST'])
def results():
if request.method == 'GET':
return redirect(url_for('search'))
else:
input_values = request.form.getlist('input_text[]')
checkbox_values = request.form.getlist('input_checkbox')
return render_template('dynamic_input_results.html',
input_values = input_values,
checkbox_values = checkbox_values)
if __name__ == '__main__':
app.run(debug = True)
dynamic_input.html:
<!DOCTYPE html>
<script>
function add_field()
{
var total_text=document.getElementsByClassName("input_text");
total_text=total_text.length+1;
field_div = document.getElementById("field_div");
new_input = "<li id='input_text"+total_text+"_wrapper'>";
new_input += "<input type='text' class='input_text' name='input_text[]' id='input_text"+
total_text+"' placeholder='Enter Text'>";
new_input += "<input type='checkbox' name='input_checkbox' value='"+total_text+"' id='input_checkbox"+
total_text+"'";
new_input += "</li>";
field_div.insertAdjacentHTML('beforeend',new_input);
}
function remove_field()
{
var total_text=document.getElementsByClassName("input_text");
document.getElementById("input_text"+total_text.length+"_wrapper").remove();
}
</script>
<div class = "container">
<h1>Give the words</h1>
<form action='/results' method="post">
<div id="wrapper">
<input type="button" value="Add TextBox" onclick="add_field();">
<input type="button" value="Remove TextBox" onclick="remove_field();">
<ol id="field_div">
</ol>
</div>
<input type='submit' value='Select'>
</form>
</div>
dynamic_input_results.html:
<ul>
{% for value in input_values %}
<li>{{value}}</li>
{% endfor %}
<hr>
{% for value in checkbox_values %}
<li>{{value}}</li>
{% endfor %}
</ul>
Output:
probably not what you were hoping for but this might do the trick if your result list is small enough
#assuming your result list is ll
alplhabet = list(string.ascii_lowercase)
if len(ll)<=len(alplhabet):
res = []
for i in map(None,alplhabet[:len(ll)],ll):
res.append(list(i))
return res

Adding a Second Text Area to a Flask App

I have a simple flask app. I tried to add a second text area to the app to add another function. I copied the text area exactly and I receive the following message when I his submit on the lower box:
Bad Request
The browser (or proxy) sent a request that this server could not understand.
Here is the code all that was changed from the original app is adding a second text area identical to the first. It appears ok but the problem arrises when I hit submit even if the text area name is changed. I don't understand how the server sees a difference between the 2nd and first box at this point. Heres the app that's being changed. Its about as sophisticated as you would expect given this question. Thx!
<!DOCTYPE html>
<html>
<head>
<title>Ven Diagram</title>
<style type=”text/css”>
#pagearea {
width: 100%;
margin: 0 auto;
}
textarea {
width: 48%;
padding: 0 0 0 0;
margin: 0 0 0 0;
}
input {
width: 80px;
height: 40px;
}
</style>
</head>
<body>
<div id="pagearea">
<h1>
This program allows you to match text. The text must be unicode.
Enter two text blocks to compare:
</h1>
<form action="/" method="post">
<textarea name="A" cols="100" rows="20"></textarea>
<textarea name="B" cols="100" rows="20"></textarea>
<br />
<input type="submit" value="Execute" />
</form>
</div>
<div id="pagearea">
<h1>
This will give add and subtract permutations for numbers.
</h1>
<form action="/" method="post">
<textarea name="A" cols="100" rows="20"></textarea>
<br />
<input type="submit" value="Execute" />
</form>
</div>
{% with messages = get_flashed_messages() %}
{% if messages %}
Results:
<pre>
{% for message in messages %}
{{ message }}
{% endfor %}
</pre>
{% endif %}
{% endwith %}
</body>
</html>
Here is the Python code:
#!flask/bin/python
import flask, flask.views
import os
import urllib
app = flask.Flask(__name__)
app.secret_key = "REDACTED"
class View(flask.views.MethodView):
def get(self):
return flask.render_template('index.html')
def post(self):
A = flask.request.form['A']
B = flask.request.form['B']
A = urllib.unquote(unicode(A))
B = urllib.unquote(unicode(B))
C = A.split()
D = B.split()
Both = []
for x in C:
if x in D:
Both.append(x)
for x in range(len(Both)):
Both[x]=str(Both[x])
Final = []
for x in set(Both):
Final.append(x)
MissingA = []
for x in C:
if x not in Final and x not in MissingA:
MissingA.append(x)
for x in range(len(MissingA)):
MissingA[x]=str(MissingA[x])
MissingB = []
for x in D:
if x not in Final and x not in MissingB:
MissingB.append(x)
for x in range(len(MissingB)):
MissingB[x]=str(MissingB[x])
#flask.flash("A:")
#flask.flash(A)
#flask.flash("B:")
#flask.flash(B)
#flask.flash("C:")
#flask.flash(C)
#flask.flash("D:")
#flask.flash(D)
flask.flash("Words in Both:")
flask.flash(Final)
flask.flash("Words in First Box Only:")
flask.flash(MissingA)
flask.flash("Words in Second Box Only:")
flask.flash(MissingB)
return self.get()
app.add_url_rule('/', view_func=View.as_view('main'), methods=['GET', 'POST'])
app.debug = True
if __name__ == "__main__":
# Bind to PORT if defined, otherwise default to 5000.
port = int(os.environ.get('PORT', 5000))
app.run(host='0.0.0.0', port=port)
even if you might think it's overkill. I learned that I want to use flask extensions in every possible way there is.
In your case i would recommend wtforms with flask-wtf to better handle any sort of forms.

Categories