How to Reload Flask-based Webpage after form submission [duplicate] - python

This question already has answers here:
Clear valid form after it is submitted
(4 answers)
Closed 5 years ago.
Here is my code currently (omitting libraries and other unnecessary parts):
app = Flask(__name__)
class SearchForm(Form):
inputString = TextAreaField('', [validators.DataRequired()])
#app.route('/')
def index():
return render_template('Website.html')
#app.route('/results', methods=['POST'])
def results():
...
form = SearchForm(request.form)
if request.method == 'POST' and form.validate():
inputString = request.form['inputString']
...
return render_template('Website.html', cLinkName=cLinkName, \
lLinkName=lLinkName)
if __name__ == '__main__':
app.run(debug=True, use_reloader=True)
And here is the webpage (showing only the form and the variables that are changed when the SearchForm is submitted):
<form method=post action="{{url_for('results')}}" style="text-align: center;">
<input type="text" id="inputString" name="inputString"/>
<input type=submit value='Search' name='search_btn'>
</form>
<table align="center" border="1">
<tr>
<td style='text-align: center;'>{{ cLinkName }}</td>
<td style='text-align: center;'>{{ lLinkName }}</td>
</tr>
</table>
Firstly, I have looked at Flask: redirect to same page after form submission and I believe I tried to implement what was accepted as the correct answer, but it did not work for me since I am also trying to submit variables to the updated webpage rather than just refresh the webpage.
I want to be able to submit the webpage's SearchForm and then update my webpage with the cLinkName and lLinkName produced from submitting my SearchForm more than once. Unfortunately my code is only allowing me to submit the SearchForm and then update my webpage with the cLinkName and lLinkName produced from submitting my SearchForm exactly once. And, when I try to reload the webpage I receive a "Continue Form Resubmission" pop-up. So my question is how can I get my webpage to allow me to submit the SearchForm and update itself more than once?
After further research,
Clear valid form after it is submitted, I can now ask for GET requests and ensure that I can reload the localhost/results page and submit another form, but it does not run the form through the algorithm again.

Added return redirect(url_for('results')) as last line in if request.method == 'POST' and form.validate(): body and everything worked fine.

Related

Flask form with GET and POSt request in same app route

I would like that a user can change his password saved in a mongodb via a webpage he is directed from a link in email that he gets. The link includes a specific token (in my case called "uniqueID") and looks like this /user_set_new_password&uniqueID=xxx.
My app route GET function is working to read the uniqueID and find the associated useremail(which serves as ID) in my mongoDB. I see the email displayed on the webpage. also the print function gives me the corresponding values.
However, my app rout POST function is not working. I get a bad request error message. The print functions do not work, so it not even picks up the new password from the form.
Any help appreciated!
My app-route looks like this:
`#app.route('/user_set_new_pw', methods=["GET", "POST"])
def user_set_new_pw_token():
if request.method == "GET":
data = request.args
uniqueID = data["uniqueID"]
print(uniqueID)
emailfromGET = collection.find_one({"uniqueID":uniqueID})["_id"]
print(emailfromGET)
return render_template('user_set_new_pw.html',emailfromGET = emailfromGET)
if request.method == "POST":
form = request.form
email = form["emailfromGET"]
print(email)
newpassword = form["passwort_neu"]
print(newpassword)
collection.update_one({"_id":email},{"$set":{"password":newpassword}})
return redirect("/login")`
my html form looks as follows:
`<form method="POST" action="/user_set_new_pw">
<table>
<tbody>
<div class="text">set a new password.</div>
<p></p>
<tr>
<input type="hidden" name="email" value="{{ emailfromGET }}">
</tr>
<tr>
<td>Neues Passwort</td>
<td>:</td>
<td><input type="password" name="passwort_neu" required></td>
</tr>
<tr>
<td>Wiederhole dein neues Passwort</td>
<td>:</td>
<td><input type="password" name="passwort_neu_wiederholung" required>
</tr>
</tbody>
</table>
<button type="submit">Neues Passwort speichern</button>
</form>`

Flask Redirect is Duplicating POST request

I'm doing a simple shopping website with a order confirmation page but I'm finding that there are duplicate POST requests to my /confim-order route. I have a home page that redirects on POST:
#views.route('/', methods=['GET', 'POST'])
#login_required
def home():
if request.method == 'POST':
# save information from the form for later use
session['text'] = request.form.get('samples')
session['note'] = request.form.get('note')
return redirect(url_for('views.confirm_order'))
return render_template("home.html", user=current_user)
My order confirmation function:
#views.route('/confirm-order', methods=['GET', 'POST'])
#login_required
def confirm_order():
if request.method == 'POST':
text = session['text']
note = session['note']
session.pop('text', None)
session.pop('note', None)
create_order(current_user, text, note)
return redirect(url_for('views.home'))
elif request.method == 'GET':
text = session['text']
note = session['note']
sample_list = get_samples(text, note)
return render_template("confirm.html", user=current_user, sample_list=sample_list)
There's no JavaScript in the HTML template. What's in confirm.html is essentially:
<form method="POST">
<div class="form-group">
<label for="cc">Credit Card</label>
<input type="text" class="form-control" id="cc" name="cc" placeholder="Credit Card Number" />
</div>
Click button to place order:
<p></p>
<div align="right">
<button type="submit" id="submit_btn" class="btn btn-success">Place Order</button>
</div>
</form>
This is what I see: sometimes, clicking submit works fine. Most times clicking submit results in two POST requests to confirm_order() and then I get a "This site can’t be reached" message in my browser at http://localhost:5000/confirm-order. I've been at this for almost an entire day. I put some print statements that seem to suggest the first POST to /confirm-order is initiated correctly from the template rendered we reach /confirm-order by GET from home: /. The second POST to /confirm-order came immediately after first the POST from within POST of /confirm-order. When that happens, I get the "This site can't be reached" message and I find that duplicate orders have been created.
I've searched online and most people that have duplicate POST issues are using JavaScript along with the form submission button. But my page doesn't use Javascript. If someone sees what's wrong, any help is greatly appreciated. Thank you.
EDIT: Here's the create_order() function in case something in there is causing the problem:
def create_order(user, text, note):
new_order = Order(user_id=current_user.id, text=text,
status='submitted', note=note)
db.session.add(new_order)
db.session.commit()
I'm not 100% sure this is the issue but it's the most likely thing I can think of.
I think there are some issues in your html since you don't specify the url for action. I would also use an input tag rather than button for submit.
More generally, I would also recommend following a few of the things mentioned here. So use the data in request.form rather than in the session object since you can control and validate that more explicitly within Flask (for instance if this is going into production you may want to implement WTF Forms for security reasons to prevent CSRF).
<form action="/confirm-order" method="post">
<div class="form-group">
<label for="po">Purchase Order</label>
<div class="form-group">
<label for="cc">Credit Card</label>
<input type="text" class="form-control" id="cc" name="cc" placeholder="Credit Card Number" />
</div>
Click button to place order:
<p></p>
<div align="right">
<input type="submit" id="submit_btn" class="btn btn-success">Place Order</input>
</div>
</form>

Flask form not validating with HTML [duplicate]

This question already has answers here:
Post values from an HTML form and access them in a Flask view
(2 answers)
Form is never valid with WTForms
(1 answer)
Closed 2 years ago.
I've tried looking through the documentation and other posts on here, though I'm still having trouble.
views.py
#bp.route('/')
def index():
return render_template("index.html")
#bp.route('/newSearch', methods=['GET', 'POST'])
def newSearch():
form = NewSearchForm()
if form.validate_on_submit():
# DB code
return redirect(url_for('newPage.html'))
return render_template('newSearch.html', form=form)
Once the user enters a search query and clicks "submit" it should redirect to the results page. However, It's not validating the form correctly with my current form tag.
index.html
<form action="{{ url_for('newSearch') }}" enctype="multipart/form-data" method="post">
<input class="btn btn-primary" type="submit" value="Search"></input>
</form
The button lives in the index.html. It fails to redirect to newPage.html in the case above. What is missing that's causing it to fail validation? any help would be greatly appreciated!

I have a HTML form and I need to display the calculated values below the form after user clicks the submit button

I'm trying to create a prediction model using flask, where the values are entered in the input box and the result is calculated in the python file. i want to display that value or text in the same html page below the submit button. i'm new to flask and this is the first time i'm creating a web server.
First, you need to set up a form to send data to your home route in your Html.
i.e.
<form action="/" method="POST">
<!-- input you want to work with -->
<input type="text" name="number">
<!-- submit button -->
<input type="submit" value="SUBMIT">
</form>
Make sure the method is POST
Then you need to make a flask route to accept the posted data.
Make sure it accepts both GET and POST method.
#app.route('/', methods=['GET', 'POST'])
You need to make sure to only request the form data when the method is POST.
if request.method == 'POST':
number = request.form['number']
# do something with it
result = number
else:
result = None
return render_template('index.html', result=result)
Because:
You only want the browser to load the content when the method is GET.
You can't access the form in GET request, and thus it will cause an error.
Then, put the resulted value in a variable (in my case result) and pass it to the HTML file.
i.e. (Full python code)
#app.route('/', methods=['GET', 'POST'])
def home():
if request.method == 'POST':
result = request.form['number']
else:
result = None
return render_template('index.html', result=result)
Then, in your HTML file check for the variable in which your value. And if the value exists display it on the page.
i.e.
{% if result %}
<p>Your no. is {{ result }}</p>
{% endif %}
I hope it helps. Comment if you have any doubt. ☺
Also might help:
HTTP Methods
You can check this out: https://www.youtube.com/watch?v=Pc8WdnIdXZg
Or what you can do is to simply pass the final output generated by .py file to the html template.
Example:
#app.route('/')
def home():
output = 2 #Let this be your output after using the prediction model
return render_template('index.html',output=output)
And in index.html file you can use
The output is : {{output}} <!--This line will give the output from the .py file -->

Flask: Is it possible to Mask a URL with variables?

I want to pass variables from a site to another.
This is no problem, as there are many ways to do it.
I'm struggling though, in how I can 'hide' these variables in the URL, and yet be able to get the values.
Ex.:
If I use 'request.args.get':
#page.route('/users', methods=['GET', 'POST'])
def users():
user = request.args.get('user')
return render_template('users.html', user=user)
When I click in the link, the URL generated is:
http://localhost:5000/users?user=john
My goal is to access the 'users' page, in the 'John' section, but what the user will see in the URL path is only http://localhost:5000/users
I was able to achieve my goal using:
window.history.pushState({"html":response.html,"pageTitle":response.pageTitle},"", "/users/");
I'm no Web Dev'er, just a Python/Flask enthusiast and know that 'window.history.pushState()' is meant for other purposes. I'm also aware that it a HTML5 Feature and not all browsers are compatible. But hey, it did the trick ;) .
Unless someone point out reasons I shouldn't be using this approach, this is my solution.
Thanks all for your time
If you'd only want to hide the variable name then you could use converters to create a route like 'users/<str:username>'. Your url would be http://localhost:5000/users/john.
Your can find the documentation here: http://exploreflask.com/en/latest/views.html#built-in-converters
Note that hiding the variables completely would mean, that your users would lose the ability to bookmark the page they are on. Additionaly if they bookmark /users anyways, you would have to catch the case that your variable is not sent or run into errors.
Post method can hide data and variables from URL. So you need to integrate it in your project. Here is an example.
app.py:
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/users', methods=['GET', 'POST'])
def show_users():
if request.method == 'POST':
username = request.form.get("username", None)
return render_template('post_example.html', username = username)
else:
return render_template('post_example.html')
if __name__ == '__main__':
app.run(debug = True)
post_example.html:
<html>
<head></head>
<body>
{% if username %}
Passed username: {{ username }}
{% endif %}
<form action="/users" method="post">
Username: <input type="text" name="username">
<input type="submit" name="submit" value="Submit">
</form>
</body>
</html>
Output:
You can check the HTTP methods in Flask official documentation here

Categories