Reputation: 23
I am new to programming. I am interested in developing a simple web app with two input values and two submit buttons. Numbers A and B are input by users and the product OR the sum will be shown depending on which button is pressed. When I use one button, the code works; however, I can't seem to figure out how to make both buttons work. I wrote the application in Flask and Python 3.8 and used wtforms.
Here are my codes: view.html
<table>
{% for field in form %}
<tr>
<td>{{ field.name }}</td><td>{{ field }}</td>
<td>{{ field.label }}</td>
</tr>
{% endfor %}
</table>
<form method="post" action="">
<input type="submit" name="btn" value="Add">
</form>
<p>
<form method="post" action="">
<input type="submit" name="btn" value="Multiply">
</form></p>
<p>
{% if result != None %}
{{result}}
{% endif %}
</p>
Python code views.py
@app.route("/comp", methods=['GET', 'POST'])
def comp():
form = InputForm(request.form)
if request.method == 'POST' and form.validate():
if request.form["btn"] == "Add":
result = add(form.A.data, form.B.data)
elif request.form["btn"] == "Multiply":
result = mul(form.A.data, form.B.data)
else: result = None
return render_template('view.html', form=form, result=result)
I defined mul() and add() functions in a separate file, as I plan to expand the application further in the future. Here is the function definition:
def mul(A,B):
return A*B
def add(A,B):
return A+B
My input.py file:
from wtforms import Form, FloatField, validators
class InputForm(Form):
A = FloatField(
label='A', default=0,
validators=[validators.InputRequired()])
B = FloatField(
label='B', default=0,
validators=[validators.InputRequired()])
Upvotes: 2
Views: 2746
Reputation: 7636
OK so I troubleshot your code. First thing first this is the result:
Flask Code :
from flask import Flask, request, render_template, url_for, flash, redirect
from wtforms import SubmitField, Form, FloatField, validators
app = Flask(__name__)
app.config['SECRET_KEY'] = 'dev'
def mul(A,B):
return A*B
def add(A,B):
return A+B
# Form
class InputForm(Form):
A = FloatField(
label='A', default=0,
validators=[validators.InputRequired()])
B = FloatField(
label='B', default=0,
validators=[validators.InputRequired()])
@app.route('/comp', methods=['GET', 'POST'])
@app.route('/', methods=['GET', 'POST']) #this so that both url will work
def comp():
result = '' #already assign a variable, else will throw error
form = InputForm(request.form)
if request.method == 'POST': #First we check if method is post **POINT 2**
if form.validate(): #Then if form is validate
print('form ok') #Test if form is ok
if request.form['btn'] == 'Add':
result = add(form.A.data, form.B.data)
print(result)
elif request.form['btn'] == 'Multiply':
result = mul(form.A.data, form.B.data)
print(result)
flash(result) # **POINT 3**
return redirect('comp') # This will make your code run forever #**4**
else:
print('form no ok ') #check if form no ok
else:
print('request is get') # if you put the form.validate with the method condition, the form will return False as soons as you render the template
return render_template('view.html', form=form, result=result)
if __name__ == '__main__':
app.run(debug=True)
HTML file:
<form method="post" action="">
<table>
<!-- Generates form fields -->
<!-- POINT 1 -->
{% for field in form %}
<td>{{ field.name }}</td><td>{{ field }}</td>
<td>{{ field.label }}</td>
</tr>
{% endfor %}
<tr>
<!-- Input are inside the form tag -->
<td><input type="submit" name="btn" value="Add"></td>
<td><input type="submit" name="btn" value="Multiply"></td>
</tr>
</table>
</form>
<!-- Print result in the browser -->
<!-- Needs to redirect to the same page -->
<!-- return redirect('comp') -->
{% for msg in get_flashed_messages()%}
<h1> {{msg}} </h1>
{% endfor%}
- So the main issue was that in the HTML the form is not together with the input field, hence it was elaborating the form separately. By adding all together then it will start to work.
- In the python file, the if request.method == 'POST' condition run simultaneously with the form hence returning the form False even before submit it.
.3 Added a Flash method so that you can see the result
.4 Add a redirect, this will flash the result to the browser, but most importantly will refresh the form and gives you possibility to add a new one.
Note that is also important to redirect the page because imagine if you want to commit it into a database, this will make you submit the form and save the changes.
Upvotes: 0
Reputation: 11360
You have 3 different forms. A
and B
are not part of either form you are submitting.
Upvotes: 1
Reputation: 11360
One of your values is "ADD", but you test for "Add". So, the equality test fails
UPDATE:
Where are you defining add()
and mul()
? Perhaps instead use:
if request.form['btn'] == 'Add':
result = form.A.data + form.B.data
elif request.form['btn'] == 'Multiply':
result = form.A.data * form.B.data
UPDATE2:
Try this to diagnose:
if request.method == 'POST' and form.validate():
print(request.form["btn"])
print(form.A.data, form.B.data)
print(request.POST)
Upvotes: 2
Reputation: 7636
If I understand the issue then try to do this:
from flask import render_template, redirect, url_for, flash, request
@app.route('/comp') #sample only
def comp():
form = InputForm(request.form)
if request.method == 'POST' and form.validate()
if request.form['btn'] == 'Add':
result = add(form.A.data, form.B.data)
elif request.form['btn'] == 'Multiply':
result = mul(form.A.data, form.B.data)
flash(result) # see the result in the browser
print('result') # see the result in the terminal
return redirect(url_for('comp'))
else:
result = None
return render_template('view.html', form=form, result=result)
to implement the flash in the html simple add this somewhere
{% for msg in get_flashed_messages()%}
<h1> {{msg}} </h1>
{% endfor %}
I always add a print statement and a flash for troubleshooting purposes in order to see where the issue is.
Upvotes: 0