Pass var value from HTML to python - python

Im using python3 and i have this HTMl which create buttons that it gets from a python list :
</style>
</head>
<body>
<ul>
{% for thing in value %}
<form method="get" action="/loader" value="submit">
<button class="button button">{{ thing }}</button>
</form>
{% endfor %}
</ul>
</body>
</html>
my python code:
#app.route("/test", methods=["GET"])
def test():
a = ["a1","a2"]
return render_template('sbutton.html', value=a)
#app.route("/loader", methods=["GET"])
def loader():
data = request.args.get()
print(data)
return render_template('loader.html', value=password)
So i will see buttons a1 and a2 in the website http://localhost/test
And when i press one of them i will redirect to /loader which is a route in my python code to another html.
I want that when i press a button, for example a1, i will get this information back to my python
inside the loader function.
i tried <form method="get" action="/loader" value="submit">
Added the value="submit but i dont get anything under print(data)
I just need to know on which button client clicked when he is redirected to /loader in my code.
I want to keep this value as a var in my python.
Thanks

data = request.args.get() should be called on the exact parameter you want to fetch, e.g. get('username'). Examples are here. As an aside, the data is passed from HTTP, the protocol that the values are transported through, not HTML, the markup language. If you want all values, request.args will return a dictionary with key-value pairs of all GET parameters passed.

I solved it, i was able to catch the button value name like this :
{% for thing in value %}
<form method="get" action="/loader">
<input type=hidden name="{{ thing }}">
<button class="button button">{{ thing }}</button>
</form>
{% endfor %}
And my code it redirects to :
#app.route("/loader", methods=["GET"])
def loader():
data = dict(request.args)
for key in data:
print(key)
return render_template('loader.html', value=password)
So now after i click the button i get the value back to my python /loader function
If client press on a1 button ill get a1 in python.

Related

Python Flask Form - html Selectbox returning 'None' as the selected item

I am creating a website server program with Flask and Python, I am relatively new to Flask. I have created a html form with a Select tag (drop down menu, single select). You can see the code below.
selectmenu.html
<!doctype html>
<html>
<body>
<form id="form" method="POST" class="selectform">
<select method="GET" size=5>
{% for x in options %}
<option value="{{x}}" SELECTED>{{x}}</option>
{% endfor %}
</select>
<input type="submit" name="go"></input>
</form>
</body>
</html>
The Python code for Flask:
app.py
#app.route('/selectmenu',methods=(['GET','POST']))
def selmenu():
optionfiles = os.listdir('options')
form = selectform()
if request.method == 'POST':
selectedoption = form.selectedoption.data
print(selectedoption)
return redirect('/')
return render_template('selectmenu.html',options=optionfiles,form=form)
And finally the Python WTForms classes code forms.py:
class selectform(FlaskForm):
optionfiles = os.listdir('userdata')
print(optionfiles)
selectedoption = SelectField('selectdropdown', choices=optionfiles,validators=[DataRequired()])
submitbutton = SubmitField('submit',validators=[DataRequired()])
But when the program called form.selectoption.data it returns None every time.
I have tried many tutorials, and Stackoverflow answers, but still can't get data from the form that isn't None.
NOTE: As you can tell I have uploaded snippets only of the code, as the actual files are all a lot larger! If you need any other bits of the code, e.g: the imports, then please ask, but I am pretty sure the error isn't the imports, for example! Otherwise I would receive an ImportError.
Thank you in advance for your help!
After finding this Stackoverflow post I found the answer.
I needed to use give the <select> tag a name, like this: name="optionsbox" in the html file.
Then do request.form.get("optionsbox") in the app.py file, instead of form.selectedoption.data. No changes needed in the forms.py file.
It seems that you are using Flask-WTF (FlaskForm) but the way you write the html part is not compliant with it.
To confirm you can replace selectmenu.html by :
<!doctype html>
<html>
<body>
<form method="POST">
{{ form.selectedoption() }}
{{ form.csrf_token }}
{{ form.submitbutton(class_='btn btn-primary') }}
</form>
</body>
</html>
If it is the case you might have a look at https://flask-wtf.readthedocs.io/en/stable/quickstart.html and https://flask.palletsprojects.com/en/1.1.x/patterns/wtforms/#forms-in-templates (for the easy template).
(And return render_template('selectmenu.html',options=optionfiles,form=form) can be replaced by return render_template('selectmenu.html',form=form) )

Getting selected element of python list

I have a list of 6 elements. I get it as a dropdown through bootstrap-select. I can receive element of list in the console only if the form is submitted for handling.
Main question is:
How to make it so that when I select an element, I can immediately get it(print it) in the console, before submitting the form?
app.py
description = ['one','two','three','four','five','six']
#app.route('/', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
docs = request.form.getlist('sel')
print(docs)
return render_template('login.html', description=description)
return render_template('login.html', description=description)
login.html
<form action="" method="POST" class="form-inline">
<select id='sel' name='sel' class="selectpicker" multiple data-live-search="true">
{% for desc in description %}
<option value="{{desc}}">{{desc}}</option>
{% endfor %}
</select>
<button type="submit" class="btn btn-primary">Identify</button>
</form>
<script type="text/javascript">
$('select').selectpicker();
</script>
If you want to print in the console, you don't need to work on the app.py, however, you need to work on your login.html.
To enable this, your answer is onchange, which is predefined for the <select>, captures your data when you select an option. No need to have a submit button either.
UPDATED ANSWER: The <p> waits for the value, which is being set inside our function printValue()
<select id='sel' name='sel' class="selectpicker" multiple data-live-search="true" onchange="printValue(this)">
{% for desc in description %}
<option value="{{desc}}">{{desc}}</option>
{% endfor %}
</select>
<p id="mySelectedValue" style="margin-top: 10px;"></p>
<!-- In your script, call your function, which prints the data in your console-->
<script type="text/javascript">
function printValue(selectedItem){
$('#mySelectedValue').html(selectedItem.value);
}
</script>
In the method printValue(), you print your data value using the method :). You can do anything, here, like adding to selected item to your array or Map. It is upto, we're just printing in console for the sake of requirement :)
This is the SNIPPET for the REFERENCE on how onchange works in SELECT.
function printValue(selectedItem){
console.log(selectedItem.value);
}
<select class="form-control" id="your_id" onchange="printValue(this)">
<option value="Value1" selected>Value1</option>
<option value="Value2">Value2</option>
<option value="Value3">Value3</option>
</select>

Displaying multiple flask variables from different forms at once in HTML template

I have 2 separate forms on a html template called queries.html, one for inputting a company name and one for inputting keywords as seen below.
<form method="POST">
<p>Enter Company Name:</p>
<p><input type="text" name="company_name"></p>
<p><input type="submit" value="submit"></p>
</form>
<p> Name: {{ name }} </p>
<form method="POST">
<p>Enter Keywords:</p>
<p><input type="text" name="keywords"></p>
<p><input type="submit" value="submit"></p>
</form>
<p> Keywords: {{ keywords }}</p>
I want to be able to display the form input in the paragraph tags seen below each form.
Below is the relevant flask code:
#app.route('/queries/', methods=['GET', 'POST'])
def queries():
if request.method == 'POST':
if request.form['company_name']:
name = request.form['company_name']
return render_template('queries.html', name=name)
elif request.form['keywords']:
keywords = request.form['keywords']
return render_template('queries.html', keywords=keywords)
return render_template('queries.html')
My problems are, firstly, the company name when entered does display fine where the {{ name }} element is as it should but when inputting a keyword I get a 'bad request' error. Secondly, I did previously have both inputs working but when I would use one form, it would wipe the displayed data from the other, e.g. when inputting a keyword after having already input and displayed a company name, the keyword would appear at the {{ keyword }} element as it should but the company name would disappear. After some research I may need to use AJAX to keep the all elements displayed but not sure if i'm looking in the right direction. It seems this should be a relatively simple issue to solve, please help! Thanks in advance to any responses.
In Place of :
request.form['company_name']
request.form['keywords']
Use this :
request.form.get("company_name")
request.form.get("keywords")
Flask throws error if there is no value in the form input. Using form.get the flask will try to get the value and will handle if there is no value.

Unsure how to post form data in Unit Test

I have a HTML template which submits a form containing the results of a user selection. This form is posted to a python function in "routes.py" which adds to a database, based on the value of this selection. I am trying to run a unit test on this function, however do not know how to post the form within the unit tests file.
Here is the relevant part of the form in the HTML template:
<form method="POST" action="{{ url_for('select') }}">
<div class="info">
<div >
<div >
<span>Select a car</span>
<br/>
<br>
<select name="car_select">
{% for i in cars %}
<option>{{i}}</option>
{% endfor %}
</select>
</div>
<br><br>
<button type="submit" onclick="time()">Vote</button>
</div>
</form>
Here is the relevant part of my function in "routes.py", that I am running the unit test on:
#app.route("/select" , methods=['GET', 'POST'])
def select():
select = request.form.get('car_select')
Here is the Helper Function that I have used in my unit test to initiate the "select" function (INCORRECT):
def select(self, car):
return self.app.post("/select", data=dict(car_select=car), follow_redirects = True)
What I expect this Helper Function to do, is simulate the POST performed by the HTML form method, such that "request.form.get('car_select')" is equal to the "car" parameter of the helper function.
You can use flask's built-in test_client:
app.test_client().post("/select", data=dict(car_select=car))

I have another method about getting the list of checkbox

A method that is recommended by most of people:
files_form_checked_chkbox = request.POST.getlist("file_of_chkbox")
for every_file in files_form_checked_chkbox:
#do somethig
This is B method that I find:
keys = request.POST.keys()
for key in keys:
if key != "csrfmiddlewaretoken":
#do somethig
This is my template:
<p>List</p>
<form action="..." method="post">
{% csrf_token %}
{% for key in keys %}
<p>
<input type="checkbox" name="file_of_chkbox" value="{{key}}">
<a href="..." >{{key}}</a>
</p>
{% endfor %}
<input type="submit" value="Delete files" />
</form>
Both methods can do same thing.
I see. It's sure that A is better than B and A is explained many time.
I use request
But I want to understand why B is't recommended with reson.
B is not doing the same thing as A.
While looping over request.POST.keys() you are doing a lot of extra work by getting the POST parameters you don't even need.
First option is doing exactly what you need to do - get the list of checkbox values. And it is readable.
I prefer the B method, this one implements the "Synchronizer token pattern" to prevent Cross-site request forgery vulnerability
Learn more about CSRF:
http://en.wikipedia.org/wiki/Cross-site_request_forgery
https://www.owasp.org/index.php/Cross-Site_Request_Forgery_%28CSRF%29_Prevention_Cheat_Sheet

Categories

Resources