BadRequestKeyError [duplicate] - python

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')

Related

How to add data to a specific user flask-SQLAlchemy [duplicate]

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.

'Method Not Allowed: The method is not allowed for the requested URL.' when submitting text entry

I am running flask python along with HTML, and the problem is simple:
It gives me error 405: Method Not Allowed: The method is not allowed for the requested URL. I have looked this up and people say to include methods=['GET', 'POST'] in the page route, but I already have this.
Python code:
#app.route('/')
#app.route('/home/', methods=['GET', 'POST'])
def home():
global count
guess = request.form.get('guess')
result, valid = guess_word(guess, word, words)
print(result, valid)
try:
guesses[count-1][2] = 'p'
except:
guesses[count-1][2] = ''
if count < 6:
if valid:
guesses[count][0] = guess
guesses[count][1] = result
session['guesses'] = guesses
if valid:
count += 1
return render_template('index.html', guesses=session['guesses'])
HTML code:
<div class="container2">
<form method="post">
<input type="text" placeholder="Guess" class="text-input" name="guess">
</form>
</div>
This worked before, and I changed (what I thought was) nothing, but it suddenly stopped working. It gives me the error when I submit the text entry.
Your form has no action attribute i.e. you have not explicitly said where your data should go to when you submit your form. In the absence of an action attribute, it will assume your home page which is / and from your routing, this does not support POST.
2 possible solutions
Add the action attribute to your form
<form action ="home" method ="post">
Keep your data as is and add support for POST to your route for / i.e. change your routing code to
#app.route('/', methods=['GET', 'POST'])
#app.route('/home/', methods=['GET', 'POST'])

Flask request.form not retrieving any data

I'm posting data to the following Flask view using an HTML form. For some reason, the server is never created. I've confirmed that the create_server method works from the interpreter. Another form I'm using to log in works. Why isn't this working?
#app.route('/add-server/', methods=['GET', 'POST'])
def add_server_view():
if request.method == 'post':
server_name = request.form['server_name']
create_server(server_name)
return redirect(url_for('index')
return render_template('add_server.html')
<form method=post>
<input name=server_name>
</form>
request.method will be in all caps and the comparison is case sensitive.
if request.method == 'POST':
This code in Werkzueg forces the method name to uppercase for consistency.

Problems redirecting to dynamic URLs in Flask with 'action'

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

Flask - POST - The method is not allowed for the requested URL

I just started learning Flask but I meet troubles with the POST method.
Here is my (very simple) Python code :
#app.route('/test')
def test(methods=["GET","POST"]):
if request.method=='GET':
return('<form action="/test" method="post"><input type="submit" value="Send" /></form>')
elif request.method=='POST':
return "OK this is a post method"
else:
return("ok")
when going to :
http://127.0.0.1:5000/test
I successfully can submit my form by clicking on the send button but I a 405 error is returned :
Method Not Allowed
The method is not allowed for the requested URL.
It is a pretty simple case, but I cannot understand where is my mistake.
You gotta add "POST" in the route declaration accepted methods. You've put it in the function.
#app.route('/test', methods=['GET', 'POST'])
def test():
if request.method=='GET':
return('<form action="/test" method="post"><input type="submit" value="Send" /></form>')
elif request.method=='POST':
return "OK this is a post method"
else:
return("ok")
See : http://flask.pocoo.org/docs/0.10/quickstart/

Categories

Resources