Why BadrequestKeyError is showing? - python

I am making a small project - Reminider System. I have a form which accepts values from users and inserts into the database table. The problem is occurring while fetching a value from a textbox. Below is my code and also I am giving what error am getting.
<form method="POST" action="">
<input type="hidden" name="unique" value="{{session.UID}}" disabled="true">
<button type="submit" class="btn btn-primary">Confirm</button>
</form>
This is my template
#app.route('/home/set_reminder',methods=['POST'])
#is_logged_in
def set_reminder():
if request.method=='POST' and form.validate():
uid = request.form['unique']
I am getting the error in this line uid = request.form['unique']. Not getting why it cannot fetch the value.
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'unique'
And this is the error which am getting.
Please help me out.

In your html, the uid input is disabled, so the browser will not send uid in a POST request's body. This causes the error when you try to access request.form.uid - it doesn't exist.
You could use readonly rather than disabled if the value must be returned by the browser.
See this answer for a little more information on BadRequestKeyError.

Related

Understanding request.data in django view

I tried looking at different resources on the internet regarding this request and request.data in django, but I couldn't fully understand it.
Why this request parameter is kept inside the function? What are we passing in this request parameter?? Also, what does this request. data do??
def index(request):
content = {
'Blogdata': Blog.objects.all(),
}
return render(request, 'index.html', content)
def somefunction (request):
data=request.data
As you can see I have two functions above both of them have request paramter inside the function. Also, I need the explanation on this request.data as this has to be used multiple times.
First, you should understand about HTTP Request(Header, Body). When you type in form and send to server, browser get data with name and add values into body request. In the backend server, we will get data from body with name.
Example:
I have form fill your name:
<form action="/signin" method="get" name="myForm">
<label for="name">Your name:</label>
<input type="text" id="name" name="name"><br><br>
<input type="button" value="Send form data!">
</form>
You type name : "Khoa", browser get values "Khoa" from input and add key:values with name in . Like this: "name": "Khoa"
In server django, you can get data with using request.data.get("name") = "Khoa"
request.data is body HTTP send to servere, "name" is key part of body have values is "Khoa"

Flask not getting cookies

I'm making backend for my website and it requires flask setting cookies. When I set the cookies, it works fine, but when I try to get them with request.cookies.get('name') it returns None. I tried just returning request.cookies and all that was there was my GA cookies, not the one that I set. Am I doing something wrong? Here's my code:
#app.route("/setcookie", methods=["GET", "POST"])
def setcookie():
resp = make_response(render_template("index.html"))
resp.set_cookie("authToken", "testestestestestestes", max_age=1)
return resp
#app.route("/getcookie", methods=["GET" ,"POST"])
def getcookie():
return request.cookies
index.html form:
<form action="/setcookie" method="POST">
<button type="submit">Set</button>
</form>
<form action="/getcookie" method="POST">
<button type="submit">Get</button>
</form>
I compared the GA cookies to the cookies that I set and the only difference was the name and value so that confuses me even more. I also don't need to do anything with them on the frontend, they only need to be read by flask. Can someone help? Thanks
You set max_age to 1 second, your cookie just gets expired, try increasing max_age value

When handling a form POST in a Django views.py, it appears to ignore the HttpResponse type

I have a Django application that generates a table of data. I have a form where you enter parameters and click one button to see the results or another to download a CSV. Seeing the results is working, but downloading the CSV is not.
I handle the response in the views.py, set the content type and disposition, and return the response. Rather than downloading the CSV, it displays the data as text. (I tried both StreamingHttpResponse and plain HttpResponse.) The same exact code works when handling a URL passing in the parameters. So, I tried a HttpResponseRedirect instead, and it does nothing. I even tried just redirecting to a plain URL, with no effect. I believe the response type is being ignored, but I don't know why.
html:
<form action="" method="post" class="form" id="form1">
{{ form.days }} {{ form.bgguserid }}
<input type="submit" value="Go!" id="button-blue"/>
<input type="submit" name="csv-button" value="CSV" id="csv-button"/>
</form>
views.py attempt 1:
def listgames(request, bgguserid, days=360):
if 'csv-button' in request.POST:
# create CSV in variable wb
response = StreamingHttpResponse(wb, content_type='text/csv')
response['Content-Disposition'] = 'attachment; filename="collectionvalue.csv"'
return response
attempt 2, the same but with:
response = HttpResponseRedirect ('/collection/{0}/csv/{1}/'.format(bgguserid,days))
I'm open to other solutions like a client-side redirect to the functioning URL, but I don't want to lose the form validation, and my HTML/javascript skills are weak.
I figured out the problem.
The code in views.py (which I partly copied from somewhere) was creating a new HttpRequest object from the return value of the form handling method.
def indexform(request):
if request.method == 'POST':
form = IndexForm(request.POST)
# Check if the form is valid:
if form.is_valid():
# process the data in form.cleaned_data as required
response = listgames(request, bgguserid=form.cleaned_data['bgguserid'], days=form.cleaned_data['days'])
# redirect to a new URL:
return HttpRequest(response)
By changing that last line to just return response, it works as intended. Sorry for wasting anyone's time.

Getting error: Could not find session for *blob_key*

Im trying to make a form where users can upload a file. And I have a form that takes the users arguments and posts them to the UploadHandler that is mapped to the url that is passed as parameter to the renderfunction. It works up to the point that it renders the form, but when submitting the file it redirects me to a blank page and the console shows me the error:
ERROR 2013-03-17 11:53:30,769 dev_appserver_blobstore.py:404] Could not find session for ahhkZXZ-a3Vyc3NhbW1hbmZhdHRuaW5nYXJyGwsSFV9fQmxvYlVwbG9hZFNlc3Npb25fXxgxDA
INFO 2013-03-17 11:53:30,779 dev_appserver.py:3104] "POST /_ah/upload/ahhkZXZ- a3Vyc3NhbW1hbmZhdHRuaW5nYXJyGwsSFV9fQmxvYlVwbG9hZFNlc3Npb25fXxgxDA HTTP/1.1" 404 -
Im still new at this but I can't seem to find whats going on. I understand that the mappings somehow f***s up, but still I don't understand why it doesn't redirect me to the correct handler (SummaryHandler)?
The class that serves the form for file upload:
class CreateHandler(BaseHandler):
def get(self):
self.render('create.html', upload_url = blobstore.create_upload_url('/upload'))
The html-form ('create.html'):
<h2 class="main-title">Upload a file!</h2>
<form action="{{upload_url}}" method="post" enctype="multipart/form-data">
<label>
<div>Upload:</div>
<input type="file" name="file" accept="application/pdf"><br>
</label>
<div class="error">
{{file_error}}
</div>
<br>
<input type="submit" name="submit" value="Submit">
</form>
The uploadhandler that takes the form args:
class UploadHandler(blobstore_handlers.BlobstoreUploadHandler):
def post(self):
upload_files = self.get_uploads('file')
blob_info = upload_files[0]
#validation of form-vars
have_error=False
file_data=dict()
if not (blob_info.content_type == 'application/pdf'):
file_data['file_error']="You can only upload files in pdf-format."
have_error=True
if have_error:
self.render('create.html', **file_data)
else:
#'parent' is just some stuff for organising the database.
#Not important in this context
the_file = A_File(parent = summary_key(),
file_key=str(blob_info.key()))
the_file.put()
if the_file:
self.redirect('/summary/%s' % str(the_file.key().id()))
else:
_error="Could not find the file"
self.render('welcome.html', error=_error)
The application handlers and their mappings:
app = webapp2.WSGIApplication([
(r'/', WelcomeHandler),
(r'/create', CreateHandler),
(r'/upload', UploadHandler),
(r'/summary/(\d+)', SummaryHandler) #I have not included this handler in the text
], debug=True)
It might be the fact that this session expired or it was used. The urls that created using create_upload_url have an expiration (I think 10 min). Before actually posting you might want to refresh that URL using JavaScript.
Also if for any reason the file was uploaded in the Blobstore you won't be able to use the same URL again, it is only good for one request (could have multiple files though).
In your example, try to remove all the file specific checks, try to upload something and check through the administrative console in the Datastore Viewer if you have any blobs or session keys. This can be accessed through this URL:
http://localhost:8080/_ah/admin/datastore

What is the cause of the Bad Request Error when submitting form in Flask application?

After reading many similar sounding problems and the relevant Flask docs, I cannot seem to figure out what is generating the following error upon submitting a form:
400 Bad Request
The browser (or proxy) sent a request that this server could not understand.
While the form always displays properly, the bad request happens when I submit an HTML form that ties to either of these functions:
#app.route('/app/business', methods=['GET', 'POST'])
def apply_business():
if request.method == 'POST':
new_account = Business(name=request.form['name_field'], email=request.form['email_field'], account_type="business",
q1=request.form['q1_field'], q2=request.form['q2_field'], q3=request.form['q3_field'], q4=request.form['q4_field'],
q5=request.form['q5_field'], q6=request.form['q6_field'], q7=request.form['q7_field'],
account_status="pending", time=datetime.datetime.utcnow())
db.session.add(new_account)
db.session.commit()
session['name'] = request.form['name_field']
return redirect(url_for('success'))
return render_template('application.html', accounttype="business")
#app.route('/app/student', methods=['GET', 'POST'])
def apply_student():
if request.method == 'POST':
new_account = Student(name=request.form['name_field'], email=request.form['email_field'], account_type="student",
q1=request.form['q1_field'], q2=request.form['q2_field'], q3=request.form['q3_field'], q4=request.form['q4_field'],
q5=request.form['q5_field'], q6=request.form['q6_field'], q7=request.form['q7_field'], q8=request.form['q8_field'],
q9=request.form['q9_field'], q10=request.form['q10_field'],
account_status="pending", time=datetime.datetime.utcnow())
db.session.add(new_account)
db.session.commit()
session['name'] = request.form['name_field']
return redirect(url_for('success'))
return render_template('application.html', accounttype="student")
The relevant part of HTML is
<html>
<head>
<title>apply</title>
</head>
<body>
{% if accounttype=="business" %}
<form action="{{ url_for('apply_business') }}" method=post class="application_form">
{% elif accounttype=="student" %}
<form action="{{ url_for('apply_student') }}" method=post class="application_form">
{% endif %}
<p>Full Name:</p>
<input name="name_field" placeholder="First and Last">
<p>Email Address:</p>
<input name="email_field" placeholder="your#email.com">
...
The problem for most people was not calling GET or POST, but I am doing just that in both functions, and I double checked to make sure I imported everything necessary, such as from flask import request. I also queried the database and confirmed that the additions from the form weren't added.
In the Flask app, I was requesting form fields that were labeled slightly different in the HTML form. Keeping the names consistent is a must. More can be read at this question Form sending error, Flask
The solution was simple and uncovered in the comments. As addressed in this question, Form sending error, Flask, and pointed out by Sean Vieira,
...the issue is that Flask raises an HTTP error when it fails to find a
key in the args and form dictionaries. What Flask assumes by default
is that if you are asking for a particular key and it's not there then
something got left out of the request and the entire request is
invalid.
In other words, if only one form element that you request in Python cannot be found in HTML, then the POST request is not valid and the error appears, in my case without any irregularities in the traceback. For me, it was a lack of consistency with spelling: in the HTML, I labeled various form inputs
<input name="question1_field" placeholder="question one">
while in Python, when there was a POST called, I grab a nonexistent form with
request.form['question1']
whereas, to be consistent with my HTML form names, it needed to be
request.form['question1_field']

Categories