I am new to Flask and I'm trying to build a simple web app. Basically what I have on the home page is a text input box and a submit button.
After clicking submit, it shows some result based on the text that was inputted (for now it's hardcoded in the code below) and also 2 buttons (positive/negative) to add the inputted text to a specific file (either with a "positive" or "negative" label).
However, the problem I face is with these 2 buttons: they don't do anything when clicked.
Here is what I have for now:
The Python Flask app
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def index():
return render_template('index.html')
#app.route('/process-data', methods=['GET', 'POST'])
def process_data():
if request.method == 'GET':
return render_template('index.html')
if request.method == 'POST':
# get the text from the form that was filled in
input_text = request.form['text']
# if submit button is clicked
if request.form['submit'] == 'Submit':
final_result = 'stackoverflow is the best'
if request.form['submit'] == 'Positive':
f = open('dataset/dataset.tsv', 'a')
f.write(input_text + '\t' + 'positive')
# if negative button is clicked
if request.form['submit'] == 'Negative':
f = open('dataset/dataset.tsv', 'a')
f.write(input_text + '\t' + 'negative')
# show the result on the page
return render_template('index.html', result=final_result, text=input_text)
The index.html file
<!doctype html>
<form action="/process-data" method="post" role="form">
<label for="text">Text:</label>
<input type="text" name="text" placeholder="Input sentence here">
<input type="submit" name="submit" value="Submit">
</form>
{% if result is not none %}
{{ result }}
<h2>Add to dataset</h2>
<form action="/process-data" method="post" role="form">
<label for="add-dataset">This sentence was:</label>
<input type="submit" name="submit" value="Positive">
<input type="submit" name="submit" value="Negative">
</form>
{% endif %}
</html>
Create your / route and have it simply return the index template and nothing else like this:
#app.route('/', methods=['GET', 'POST'])
def index():
return render_template('index.html')
Then assign the other route to another function which will do the processing. I wouldn't call it index, maybe something like process-data, like this:
#app.route('/process-data', methods=['GET', 'POST'])
def process_data():
# put the body of your function here
# ...
# ...
# ...
return render_template('index.html', result=final_result, text=input_text)
Finally, you just need to update your form action accordingly:
<form action="/process-data" method="post" role="form">
Check whether you have set the configuration setting SESSION_COOKIE_SECURE. If you're working in localhost or through an unsecure line and you have set SESSION_COOKIE_SECURE=True then no session cookie will be sent and as such no forms, csrf protection and various other operations will work. Instead use SESSION_COOKIE_SECURE=False under these circumstances.
Related
I am trying to build a simple Flask app in Python with two radio buttons and a "refresh" button, where, on clicking on the refresh button, the page reloads and displays the radio button selection on the previous page.
Routes.py:
#app.route("/")
def display():
return render_template("index.html", choice=choice)
if request.form['submit'] == 'Refresh':
choice= request.form.get("Choice")
return redirect(url_for('/'))
index.html:
<html>
<head>
<title>Choice</title>
</head>
<body>
<h2>Choice</h2>
<hr>
{{choice}}<br>
<form action="">
<input type="radio" name="Choice" value="Choice1"><span>Choice 1/span><br/>
<input type="radio" name="Choice" value="Choice2"><span>Choice 2</span>
<input type="submit" name="refresh" value="Refresh">
</form><br>
</form> </body>
</html>
Apply the below changes and check if it works!
render_template, request, redirect, url_for was used but not imported. Try to import them.
from flask import Flask, render_template, request, redirect, url_for
To retrieve POST data, you can use request.form.
To retrieve GET data, you can use request.args.
Try the below code if you want to use request.args:
#app.route("/")
def display():
choice = request.args.get('Choice','None Selected')
return render_template("index.html", choice=choice)
if request.args.get('refresh') == 'Refresh':
return redirect(url_for('display',Choice=choice))
Try the below code if you want to use request.form:
#app.route("/",methods = ['POST', 'GET'])
def display():
if request.method == 'GET':
choice = request.args.get('Choice','None Selected')
return render_template("index.html", choice=choice)
if request.method == 'POST':
choice= request.form.get("Choice")
return redirect(url_for('display',Choice=choice))
In index.html add <form action="" method="POST"> to send the form data
Problem transferring variables across views I tried using sessions and could not get the connection to work. Say I have two pages, a home and page2. I have a flask app that will take user input from the home and print out input on page2.
For example, if you start my app, you will see this as the home page:
This part works fine, I am able to enter a value.
What I want to happen next, is after you click submit, page2 is generated showing what was just entered:
Whatever string value was entered on home should show up in the highlighted portion.
I have the following app.py file:
from flask import Flask, render_template, request, session
app = Flask(__name__)
#app.route('/', methods=['GET', 'POST'])
def home():
stringval = ''
if request.method == 'POST' and 'stringval' in request.form:
stringval = request.form.get('stringval')
session["stringvalue_topass"] = stringval
return render_template('page2.html', stringval = stringval)
return render_template("home.html")
#app.route('/page2', methods=['GET', 'POST'])
def page2():
stringvalue_get = session.get('stringvalue_topass')
return render_template('page2.html', stringvalue_get = stringvalue_get)
if __name__ == '__main__':
app.run(debug=True)
The following home.html:
<!doctype html>
<h1>Enter Value </h1>
<div class="main">
<form class="pure-form" method="POST" action="/page2">
stringval:<br>
<input type="text" name="stringval"><br>
<button type="submit" class="pure-button pure-button-primary" value="Submit">Submit!</button>
</form>
</div>
</body>
And the following page2.html
<!doctype html>
<h1>You have selected </h1>
<div class="main">
{% if stringvalue_get %}
<pre>
{% print(stringvalue_get) %}
</pre>
{% endif %}
</div>
</body>
Okay, there are a few issues here. Firstly, the action attribute of your form in home.html is set to "/page2". This means that when the form is submitted, the POST request is going to the /page2 endpoint rather than to the /home endpoint, where you have written the code for handling the form submission. We can fix this by just deleting the action attribute, as this means the form will post to then endpoint that loaded it - in this case /home.
Secondly, Flask sessions cannot be used without setting a secret key to encrypt the session. This can be done by assigning a value to app.secret_key, like so:
app = Flask(__name__)
app.secret_key = b"my_secret_key"
Finally, instead of passing the string to the template like so: render_template('page2.html', stringval = stringval), (note also that this should be stringval_get = stringval), you can access the session object directly from templates already. So, in all, we can change your application code to:
app.py:
from flask import Flask, render_template, request, session
app = Flask(__name__)
app.secret_key = b"my_secret_key"
#app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST' and 'stringval' in request.form:
session["stringvalue_topass"] = request.form.get('stringval')
return render_template('page2.html')
return render_template("home.html")
#app.route('/page2', methods=['GET', 'POST'])
def page2():
return render_template('page2.html')
And your templates to:
home.html:
<!doctype html>
<h1>Enter Value </h1>
<div class="main">
<form class="pure-form" method="POST">
stringval:<br>
<input type="text" name="stringval"><br>
<button type="submit" class="pure-button pure-button-primary" value="Submit">Submit!</button>
</form>
</div>
</body>
page2.html:
<!doctype html>
<h1>You have selected </h1>
<div class="main">
{% if 'stringvalue_topass' in session %}
<pre>
{% print(session["stringvalue_topass"]) %}
</pre>
{% endif %}
</div>
</body>
Hi The idea of my code is to allow the user to submit an ID through using this form
#app.route('/')
def home():
return '''
<form method="get">
<textarea name="textbox"></textarea>
<button type="submit" name="submit">Submit</button>
</form> '''
Then the user ID is read by this route and other calculations are done
#app.route('/')
def api_id():
text = request.form.get('textbox')
## Do other calculations
My issue is that when the user inputs the ID nothing happens, only the URL changes but the calculations are not reflected.. Can you please help?
You need to specify the route that will receive the POST request from the form:
#app.route('/')
def home():
return '''
<form method="POST" action="/get_id">
<textarea name="textbox"></textarea>
<button type="submit" name="submit">Submit</button>
</form>
'''
#app.route('/get_id', methods=['POST'])
def get_id():
id = flask.request.form['textbox']
#do something
I'm running a small Flask test and attempting to do the following:
I have two forms.
The first - receives users input, then has a submit button. When the submit button is pressed I would like to 1.) execute a back-end Python program using the two values from 'doritos' and 'oreos' then 2.) return some relative text back to the user (i.e., successful) on the same page, next to the button or in some text window.
Question - How can I pass the values received from this form back to foo?
Question - How can I return a text value back to the user?
The second - basic buttons which call a Python program and return and return some relative text back to the user (i.e., successful). I'm assuming I can use the above questions to answer this as well.
Documentation I continue to see online uses app.route and routes the user to another page with results. I want to keep the user on the same page and just return text. If this is too vague you can tell me to RTFM. Just having a hard time figuring this out.
See below for my code:
index.html:
<form action="/foo" method="post">
CHIPS:<br>
<input type="text" name="doritos"><br>
SNACKS:<br>
<input type="text" name="oreos"><br>
<input type="submit" value="Submit">
</form>
<form action="/coo" method="post">
<input type="submit" name="pita" value="pita"><br>
<input type="submit" name="chip" value="chip"<br>
</form>
app.py
from flask import render_template
from app import app
#app.route('/')
#app.route('/index')
def index():
return render_template("index.html", title='Home')
#app.route('/foo')
def foo():
try:
..receive user-input values..
..do some back end actions..
return 'Successful.'
except:
return 'Failed.'
#app.route('/coo')
def coo():
try:
if request.form['pita']:
..do some back end actions..
return 'Successful.'
elif request.form['chip']:
..do some back end actions..
return 'Successful.'
except:
return 'Failed.'
Flask has the Jinja2 built in (you're already using it in the form of render_template), so one simple solution to this problem could be to create a template with your forms, and pass a "success" or "fail" message to the template when data is posted.
Consider the following index.html template snippet:
<form action="/" method="post">
CHIPS:<br />
<input type="text" name="doritos"><br />
SNACKS:<br />
<input type="text" name="oreos"><br />
<input type="submit" value="submit">
</form>
{% if fooResponse is not none %}
{{ fooResponse }}
{% endif %}
<form action="/" method="post">
<input type="submit" name="pita" value="pita"><br />
<input type="submit" name="chip" value="chip"><br />
</form>
{% if cooResponse is not none %}
{{ cooResponse }}
{% endif %}
Your Python might then look something like this (assuming you don't want to navigate away from ///index, and based on your question I'm assuming that the output shown from each form is non-persistent and mutually exclusive):
#app.route('/')
#app.route('/index', methods=['GET', 'POST'])
def index():
if request.method == "GET":
return render_template("index.html")
if request.form["submit"] == "submit":
doritos = request.form["doritos"]
oreos = request.form["oreos"]
success = process(doritos, oreos)
return render_template("index.html", fooResponse="Successful" if success else "Failed")
elif request.form["submit"] == "pita":
success = process("pita")
return render_template("index.html", cooResponse="Successful" if success else "Failed")
elif request.form["submit"] == "chip":
success = process("chip")
return render_template("index.html", cooResponse="Successful" if success else "Failed")
You can link your form submission to an ajax call in javascript. The ajax function would send the data to an api, python would do all calculations and send a response. The ajax function receives that response in the front end and displays whatever text/data you want in the frontend.
Consider something like:
$.ajax({
type: "POST",
url: "/api/oreos-and-doritos",
dataType: "json",
contentType: "application/json",
data: JSON.stringify(data-from-form),
success: function (data) {
// do whatever changes are needed in the frontend,
// like displaying a message
$('#msg').text(data);
},
error: function (xhr, error, thrown) {
// do some error handling here
}
}));
Whenever I request the page, it loads fine, but when I submit the form, I receive a 400 bad request,I believe it may be to do with the actual html , but I cannot figure out what.
Html file /admin/dashboard.html :
<div class="container">
<p><strong>Shut down server?</strong></p>
<form action="/" method="POST">
<input class="btn btn-danger" id="fred" name="fred" type="submit" value="fred"></input>
</form>
</div>
Python file :
#app.route('/admin/dashboard', methods=['GET', 'POST'])
def admin_dashboard():
if request.method == 'GET':
return render_template("/admin/dashboard.html")
if request.method == 'POST':
if request.form['submit'] == 'fred':
admin.log("Shutting down...")
#os._exit(1)
else:
return render_template("/admin/dashboard.html")
return render_template("/admin/dashboard.html")
You are posting to the / path, but the view that handles your post is at /admin/dashboard. Remove the action="/" line from your form since it's the same url that rendered the page.
If you do need a different url, use url_for('name_of_endpoint'). For example, to generate the url for def admin_dashboard():, you use url_for('admin_dashboard').
Additionally, you named your input 'fred', so you need to access request.form['fred'], or change the name of the input to 'submit'.
You are checking if a field with name submit is present in the request:
if request.form['submit'] == 'fred':
But there is no such field, the field is actually named fred:
<input class="btn btn-danger" id="fred" name="fred" type="submit" value="fred"></input>
You should either change the request check:
if request.form['fred'] == 'fred':
Or change the inputs name:
<input class="btn btn-danger" id="fred" name="submit" type="submit" value="fred"></input>
In Flask doc
We recommend accessing URL parameters with get or by catching the
KeyError because users might change the URL and presenting them a 400
bad request page in that case is not user friendly.
so maybe you can try
request.form.get('submit', '')
so your code:
if request.method == 'POST':
if request.form.get('submit') == 'fred':
admin.log("Shutting down...")
#os._exit(1)
else:
return render_template("/admin/dashboard.html")
return render_template("/admin/dashboard.html")