This question already has answers here:
Flask-SQLalchemy update a row's information
(8 answers)
Closed 11 months ago.
Hello I am making a blogging website with flask, flask-sqlalchemy, and flask-login. I am trying to figure out a way to add optional data such as a role after the account creation.
This is as far as I have gotten:
#app.route('/addpinfo', methods=["POST", "GET"])
#login_required
def accountinfo():
if request.method == "POST":
username = current_user.username
job = request.form.get("role")
user_job = Loginbase(job=job)
db.session.add(user_job)
db.session.commit()
return redirect(url_for("homebase"))
else:
return render_template("accountspecs.html")
Here is what the HTML looks like:
<form method="post">
<script src="{{url_for('static', filename='js/accountspecs.js')}}"></script>
<input class="dissapointment form-box" type="text" placeholder="Write a hobby or job title"name="role"><br>
<button class="cool-sub" type="submit" name="submit">Add Role Info</button>
</form>
Does anyone know where I can go from here? I have been having trouble trying to find a way to add that element to the account the user is currently using.
Thank you for any help ahead of time.
The solution that worked with my code was:
#app.route('/addpinfo', methods=["POST", "GET"])
#login_required
def accountinfo():
if request.method == "POST":
user = current_user
job = request.form.get("role")
user.job = job
db.session.commit()
return redirect(url_for("homebase"))
else:
return render_template("accountspecs.html")
This allowed for my role system to work. I thank Patrick for all of their help.
Related
Say I have an example flask app which basically is a small webform that would take in user input data called applet.py.(The code is taken from a online blog that shows an example flask app build).
from flask import Flask,render_template,request
app = Flask(__name__)
#app.route('/form')
def form():
return render_template('form.html')
#app.route('/data/', methods = ['POST', 'GET'])
def data():
if request.method == 'GET':
return f"The URL /data is accessed directly. Try going to '/form' to submit form"
if request.method == 'POST':
form_data = request.form
return render_template('data.html',form_data = form_data)
app.run(host='localhost', port=5000)
The input is captured in this below form.
<form action="/data" method = "POST">
<p>Name <input type = "text" name = "Name" /></p>
<p>City <input type = "text" name = "City" /></p>
<p>Country <input type = "text" name = "Country" /></p>
<p><input type = "submit" value = "Submit" /></p>
</form>
If I were wanting to send this received user input into ansible variables and then trigger the ansible script to run and execute the playbook based on the given variables. How can I do that? I have googled a lot around this, couldn't find a suitable example that fits my use case. (Disclaimer, not very knowledgeable about both flask and ansible, learning as I do). Appreciate help, reference and advice.
You can use the ansible_runner module to run your playbook (docs).
import ansible_runner
#app.route('/data/', methods = ['POST', 'GET'])
def data():
if request.method == 'GET':
return f"The URL /data is accessed directly. Try going to '/form' to submit form"
if request.method == 'POST':
form_data = request.form.to_dict()
r = ansible_runner.run(playbook='test.yml', extravars=form_data)
# check ansible return code
if r.rc != 0:
abort(400, 'Ansible error')
return ('', 204)
If your playbook takes some time to run you might be better adding the job of running it to a queue and processing it separately.
This question already has answers here:
Insert or write data to .txt file with flask
(2 answers)
Closed 1 year ago.
Is anyone wrapping up flask in python well? I have a registration form but I don't know how to save the data from that page, like name and password, so I can read it later.
Save to a separate file of type:
file = open(file.txt)
file.write(username + password)
does not work when I already host the page.
Firstly, can you provide your code? What would you like to create? Is it a simple web application that requires registration and authorization or is it just a form from which you would like to take some data?
Secondly, there is some good tutorials in the Internet about Flask registration. Moreover, you can read this. Here there is a Flask student book. You can search for something different if this tutorial will not actual and proper for you.
Thirdly, about saving data in the textual file .txt from flask app. You can check this answer.
UPD. For the last variant with file.
app.py
from flask import Flask, render_template, request
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/', methods = ['POST'])
def get_data():
login = request.form['login']
password = request.form['password']
if request.method == 'POST':
with open('data.txt', 'a+') as f:
f.write(str(login) + ' ' + str(password) + '\n')
return render_template("index.html")
if __name__ == '__main__':
app.run(debug = True)
templates/index.html
<html>
<body>
<form action="" method="POST">
<p>Login <input name="login" /></p>
<p>Password <input name="password" /></p>
<p><input type="submit"></p>
</form>
</body>
</html>
Disclaimer: Yes I know this might not be the right way to do it, but I just need a quick and easy fix and in this case I prefer the quick and dirty way.
I have a login.html like this:
<form method="POST" class="login-form" action="/login">
<input type="text" name="code">
<input type="submit" value="Submit">
</form>
I have two types of users who will visit this page. First type of users will have "code_A", second type of users will have "code_B". Depending on which code they will type into the form field they will be redirected to gallery or gallery2.
This is my routes.py:
code_A = "code_A"
code_B = "code_B"
#app.route("/login", methods=['GET', 'POST'])
def login():
if 'code_A' in session:
redirect(url_for('gallery'))
elif 'code_B' in session:
redirect(url_for('gallery2'))
elif request.method == 'POST':
code_post = request.form['code']
if code_post == code_A:
session['code_A'] = code_A
return redirect(url_for('gallery'))
elif code_post == code_B:
session['code_B'] = code_B
return redirect(url_for('gallery2'))
else:
return render_template("login.html")
else:
return render_template("login.html")
return render_template("login.html")
#app.route("/gallery")
def gallery():
if 'code_A' not in session:
return redirect(url_for('login'))
else:
return render_template('gallery.html')
#app.route("/gallery2")
def gallery2():
if 'code_B' not in session:
return redirect(url_for('login'))
else:
return render_template('gallery2.html')
I though I could simply take the input from the form and create a session based on the input. If the right code is in the session, the user should be redirected to gallery or gallery2, depending on the session. But with this code I always get redirected to login.html and no session is created. How do I pass the input from the form to the routes.py and create a session from it. I mean it cannot be that hard, or is it?
I am thankful for every suggestion, because I am loosing my mind over it. Thanks and best regards!
This question already has answers here:
Get the data received in a Flask request
(23 answers)
Closed 4 years ago.
Multiple questions have been asked with a similar error on SO. I have tried all of the solutions but still keep getting a beautiful error:
werkzeug.exceptions.HTTPException.wrap..newcls: 400 Bad Request: KeyError: 'username'
Below is my html form:
<form action='/login' method = "GET">
<label>Name: </label>
<input name="username" type="text">
<input type="submit" name='submit' value='submit'>
</form>
Here is the function that deals with the form data:
#app.route('/login', methods = ['GET'])
def login():
if request.method == "GET":
un = request.form['username']
return un
I have learned Bottle and transitioning towards Flask.
So far, I have tried the following:
1) GET to POST
2) request.form.get('username', None)
3) Add POST reason to the function route without any rhyme or reason.
Can somebody help me out?
You need to change the method (GET to POST) in the html file and add the method in the decorator #app.route too. Do not forget that in this case a return (GET) is required to render the html file.
#app.route("/login", methods = ['GET', 'POST'])
def login():
if request.method == "POST":
# import pdb; pdb.set_trace()
un = request.form.get('username', None)
return un
return render_template('form.html')
Tip: Learn about pdb to debug your programs more easily.
https://realpython.com/python-debugging-pdb/
https://docs.python.org/3/library/pdb.html
no need to change your form action method. but when you use GET method for sending form data your data is transmitted as URL variables and you need to read data this way:
if flask.request.method == 'GET':
username = flask.request.args.get('username')
and if you change the method to POST, read content as below:
if flask.request.method == 'POST':
username = flask.request.values.get('username')
My app has a text box and a submission button. I am trying to create and redirect to dynamic URLs in my app, that are based off of what is typed in the text box. For example, the user enters in '1234', clicks submit, then is taken to 'website.com/results/1234'. The problem seems to be that the HTML for my button doesn't want to redirect the user to the new, dynamic URL. I am passing this to the HTML with Jinja.
Here is what I have.
The user starts on the home page, that is defined like this
#app.route("/home/", methods=["GET", "POST"])
def start():
return render_template("dashboard.html")
Dashboard.html has a text box and submission button (below). As you can see, the action of this button is to redirect to {{ results_page }}, where "results_page" comes from my Python function load_results (also below) and is passed to the HTML with render_template.
<div>
<form action="{{ results_page }}" class="form-inline" method="post">
<div class="form-group">
<label for="PubmedID">Pubmed ID(s)</label>
<input type="text" class="form-control" id="PubmedID" placeholder="18952863, 18269575" name="pmid" value="{{request.form.pmid}}">
</div>
<button type="submit" id= "myButton" class="btn btn-default" data-toggle="modal" data-target="#myModal">Submit</button>
</form>
</div>
The results page of my app uses the user input to look up some information and display it.
#app.route('/results/<query>', methods=["GET", "POST"])
def load_results(query):
form = pmidForm(secret_key='super secret key')
try:
if request.method == 'POST':
query = form.pmid.data #This is the user input
results_page = "website.com/results/"+query
return(query)
#do lots of stuff using the query
return render_template('results.html', form=form, results_page = results_page)
except Exception as e:
return(str(e))
If I run my app like this, the home page is fine, but when I click "Submit", the app doesn't take in the user input or do anything with it. Simply the home page refreshes.
I am new to web development, but since this code works fine if I hardcode the button to action = "website.com/results" in the HTML, AND do without the <query> in /results/<query> for the results page, I think that only a few adjustments should be needed to make my app dynamically redirect to and load pages correctly. Right now, I'm not sure what I'm missing. Please let me know where I'm going stray.
EDIT -
Now I have implemented a handle_form function that redirects to my dynamic URL. This function properly redirects but then I get a 404 error.
#app.route('/form/', methods=["POST"]) #handles form submission
def handle_form():
form = pmidForm(secret_key='super secret key')
if request.method == "POST":
query = request.form['pmid']
return redirect('/results/'+query)
I have also edited my form in the HTML action to go to /form/
<form action="website.com/form/" class="form-inline" method="post">
<div class="form-group">
<label for="PubmedID">Pubmed ID(s)</label>
<input type="text" class="form-control" id="PubmedID" placeholder="18952863, 18269575" name="pmid" value="{{request.form.pmid}}">
</div>
<button type="submit" id= "myButton" class="btn btn-default" data-toggle="modal" data-target="#myModal">Submit</button>
</form>
With this, my site will properly redirect to /results/<query>/ (e.g. /results/1234) but I get a 404 error. Here is how I have changed my load_results
#app.route('/results/<query>', methods=["GET"])
def load_results(query):
form = pmidForm(secret_key='super secret key')
try:
if request.method == 'GET':
query = form.pmid.data #THIS IS THE USER INPUT FROM THE FORM #referencing 'class pmidForm'
return query
.
.
#do stuff
I think I am very close but need to figure out why I am getting a 404 error. My guess is that I am using "GET" incorrectly. My form in the HTML uses method="post". Since this does not match with "GET", is there no way for my load_results(query) function to retrieve the contents of the form?
EDIT 2 -
Changed handle_form to redirect with url_for:
#app.route('/form/', methods=["POST"]) #handles form submission
def handle_form():
form = pmidForm(secret_key='super secret key')
if request.method == "POST":
query = request.form['pmid']
return redirect(url_for('.load_results', query=query))
And changed load_results to not return "query"
#app.route('/results/<query>', methods=["GET"])
def load_results(query):
form = pmidForm(secret_key='super secret key')
try:
if request.method == 'GET':
query = form.pmid.data # This shouldn't work??
.
.
# do stuff with the variable "query"
With this, it's still returning the 404 Error as before. Should I not be using if request.method == GET ?
Edit 3 -
Even a very simplified load_results will give me the 404 error, so I'm not sure what's up.
#app.route('/results/<query>', methods=["GET", "POST"])
def load_results(query):
q = query
return render_template('test.html', q=q)
EDIT - 3
It seems that the accepted solution IS the correct solution to this problem, however there is an issue with uwsgi in my server that is re-directing it to the wrong location :(
Your punctual problem is that /home route function also needs to put the results_page url on the templating context.
results_page = "website.com/results"
return render_template("dashboard.html", results_page=results_page)
Since the variable is undefined, flask is calling the original endpoint on the form submission.
Your larger problem is that your appraoch isn't going to get you a dynamic results url that looks like /results/1234.
Typical approaches are to redirect on the server side when you handle the post request; or to use JavaScript in the client to get the form data and change the browser location to /results/1234.
A simplified version of how to handle this with a server side redirect might look something like this. One route that handles the form submission and another that displays results. You simply redirect from one to the other to get the nice url.
#app.route('/form', methods=["POST"])
def handle_form():
query = form.pmid.data #This is the user input
return redirect(url_for('.load_results', query=query))
#app.route('/results/<query>') *removed the method spec to handle the redirect?
def load_results(query):
.
.
# do something with query