Bad Request with Flask - python

really struggling with this bad request from flask. I know normally it caused by flask not finding the [key] in the form.. However, I've checked my form and python code 40 times and cannot see any reason that would be the case.. I have commented out each line of the python code that references request.form. I have done it 1 by 1 and I still get a bad request. However when I comment out all the lines the bad request goes away.. Any thought would be wonderful..
Python code;
if request.method == 'POST':
form = 'Add Package Form'
clientId = request.form['id']
date = request.form['date2']
strPrice = request.form['price']
price = float(strPrice)
adultlessons = request.form['adult']
juniorlessons = request.form['junior']
shortlessons = request.form['short']
playinglessons = request.form['playing']
notes = request.form['notes']
form..
<form action="/addpackage" method="post" class="sky-form">
<fieldset>
<section>
<label class="label">Select Package Date</label>
<label class="input">
<i class="icon-append fa fa-calendar"></i>
<input type="text" name="date2" id="date">
</label>
</section>
<div style="margin: -25px"></div>
<fieldset>
<section>
<label class="label">Price</label>
<label class="input">
<input type="text" name="price">
</label>
</section>
<section>
<label class="label">Adult Lessons</label>
<label class="input">
<input type="text" name="adult">
</label>
</section>
<section>
<label class="label">Junior Lessons</label>
<label class="input">
<input type="text" name="junior">
</label>
</section>
<section>
<label class="label">Short Game Lessons</label>
<label class="input">
<input type="text" name="short">
</label>
</section>
<section>
<label class="label">Playing Lessons</label>
<label class="input">
<input type="text" name="playing">
</label>
</section>
<section>
<label class="label">Notes</label>
<label class="textarea textarea-expandable">
<textarea rows="3" name="notes"></textarea>
</label>
<div class="note"><strong>Note:</strong> expands on focus.</div>
</section>
</fieldset>
</fieldset>
<!-- hidden client id -->
<input type="hidden" name="id" value="{{ client.id }}">
<!-- /hidden client id -->
<footer>
<button type="submit" name="addpackage" value="package" class="button">Add Package</button>
</footer>
</form>

This is something of a half-answer, but it was too long for a comment.
If you enable debugging in your Flask app you should get a detailed traceback indicating exactly where the problem is occurring (both in the browser and on your console).
If your application currently has something like:
app.run()
Just set the debug parameter to true:
app.run(debug=True)
If after enabling debugging you're still not sure what's causing the problem, update your question to include the traceback.
For what it's worth, if I dump your form and your code into a simple Flask app, it all seems to work just fine as long as I provide a numeric value for the price field.

Usually you'll get a 400 Bad Request in Flask while submitting a form when you try and access a form key in the request object that doesn't exist.
This is because the request.form object inherits its __getitem__ method the Multidict class in the werkzeug.datastructures module which raises a BadRequestKeyError when a key doesn't exist.

You should give the form data a default value to avoid HTTP 400 error, like this:
default_value = True
is_public = request.form.get('public', default_value)
However, I recommend you to use Flask-WTF.
With Flask-WTF, your code can be simplify to this (an example):
import ...
app = Flask(__name__)
class EditProfileForm(Form):
name = StringField('name', validators=[Length(0, 64)])
location = StringField('city', validators=[Length(0,64)])
website = StringField('website', validators=[Length(0,64), render_kw={"placeholder": "http://..."})
about_me = TextAreaField('Bio', validators=[Length(0,2000)], render_kw={"placeholder": "I'm......"})
submit = SubmitField(u'submit')
#app.route('/edit-profile', methods=['GET', 'POST'])
def edit_profile():
form = EditProfileForm()
if form.validate_on_submit():
current_user.name = form.name.data
current_user.location = form.location.data
current_user.website = form.website.data
current_user.about_me = form.about_me.data
db.session.add(current_user)
flash('Update success!', 'success')
return redirect(url_for('.user', username=current_user.username))
return render_template('edit_profile.html', form=form)
In your html file:
<form method="POST" action="/">
{{ form.hidden_tag() }}
{{ form.name.label }} {{ form.name() }}
{{ form.location.label }} {{ form.location() }}
...
</form>
By the way, if you use Flask-Bootstrap, you can just use one line to render the whole form:
{% import "bootstrap/wtf.html" as wtf %}
{{ wtf.quick_form(form) }}
I hope it will help.

Related

CSRF middleware token missing?

I'm novice adapting a simple address book database program using Django from a course I've done on Codemy.
I have a page where I enter the names, surnames etc together with a DELETE and EDIT button next to each address. There's no problem when I click the EDIT button (the form populates automatically and takes me to website/edit1,2,3,4 etc/), but when I click the 'edit' button after editing the addressee info, I get the error as below. The btn1 is the name="btn1" of the button as indicated.
GET /edit/3?csrfmiddlewaretoken=b4IkMxxxxxxxxxxxDHrDIgRnjvEWr53rL&**btn1**=140 HTTP/1.1" 200 5751
Here is my views file
from django.shortcuts import render, redirect
from .models import List
from .forms import ListForm
from django.contrib import messages
from django.http import HttpResponseRedirect
def home(request):
all_items = List.objects.all
return render(request, 'home.html', {'all_items': all_items})
def about(request):
return render(request, 'about.html', {})
def edit(request, item_id):
if request.method =='POST':
item = List.objects.get(pk=item_id)
form = ListForm(request.POST or None, instance=item)
if form.is_valid():
form.save()
messages.success(request, ('Item Had Been Edited'))
return redirect('home')
else:
item = List.objects.get(pk=item_id)
return render(request, 'edit.html', {'item': item})
def delete(request, item_id):
item = List.objects.get(pk=item_id)
item.delete()
return redirect('home')
...And here is the edit.html file
{% extends 'base.html' %}
{% block title %}To-Do-List | Edit {% endblock %}
{% block content %}
{% if item %}
{{ item.item }}
<form class="needs-validation" novalidate>
{% csrf_token %}
<div class="form-row">
<div class="col-md-6 mb-3">
<label for="validationCustom01">First name</label>
<input type="text" class="form-control" id="validationCustom01" value="{{ item.First_name }}" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
<div class="col-md-6 mb-3">
<label for="validationCustom02">Last name</label>
<input type="text" class="form-control" id="validationCustom02" value="{{ item.Surname }}" required>
<div class="valid-feedback">
Looks good!
</div>
</div>
</div>
<div class="form-row">
<div class="col-md-6 mb-3">
<label for="validationCustom03">Street</label>
<input type="text" class="form-control" value="{{ item.Street }}" id="validationCustom03" required>
<div class="invalid-feedback">
Please provide a valid city.
</div>
</div>
<div class="col-md-3 mb-3">
<label for="validationCustom03">Town</label>
<input type="text" class="form-control" value="{{ item.Town }}" id="validationCustom03" required>
<div class="invalid-feedback">
Please provide a valid city.
</div>
</div>
<div class="col-md-3 mb-3">
<label for="validationCustom05">Province</label>
<input type="text" class="form-control" value="{{ item.Province }}" id="validationCustom05" required>
<div class="invalid-feedback">
Please provide a valid zip.
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-3 mb-3">
<label for="validationCustom05">Postal code</label>
<input type="text" class="form-control" value="{{ item.Postal_code }}" id="validationCustom05" required>
<div class="invalid-feedback">
Please provide a valid zip.
</div>
</div>
</div>
<button class="btn btn-primary" type="submit" type="hidden" value="" name='btn1'>Edit</button>
</form>
<script>
// Example starter JavaScript for disabling form submissions if there are invalid fields
(function() {
'use strict';
window.addEventListener('load', function() {
// Fetch all the forms we want to apply custom Bootstrap validation styles to
var forms = document.getElementsByClassName('needs-validation');
// Loop over them and prevent submission
var validation = Array.prototype.filter.call(forms, function(form) {
form.addEventListener('submit', function(event) {
if (form.checkValidity() === false) {
event.preventDefault();
event.stopPropagation();
}
form.classList.add('was-validated');
}, false);
});
}, false);
})();
</script>
{% endif %}
{% endblock %}
I cannot locate an issue with the CSRF token. it is included just like the tutorial on the edit.html page. Not even sure if the issue is with the token?
I've gone through the tutorial time and again and cannot see an issue.
I'm a noob, so any info would be great!
Normally, when you save information after editing it in a form, you should "post" your data to the server.
It appears your form method is not set which default to get. It should be set to post.
<form method="post">...</form>
This being said, your view should also be configured accordingly. Without more details, it is hard to provide deeper answer.

can't get the POST parameters in django

I am trying to make a login-page using django, I am facing troubles in getting POST parameters
login view:
def ProcLogin(request):
if request.method == 'POST':
account_name = request.POST.get('username','')
password = ToMd5(request.POST.get('password',''))
if not account_name or not password: return HttpResponse("invalid input")
template code:
<form method="post" action="{% url 'Main:login' %}" class="login_form">
{% csrf_token %}
<div class="form-group text-right">
<label for="username">User name:</label>
<input id="username" type="text" class="form-control box_shadow">
</div>
<div class="form-group text-right">
<label for="password">Password: </label>
<input id="password" type="password" class="form-control box_shadow">
</div>
<button type="submit" class="login_btn"></button>
</form>
Output when testing it:
invalid input
everything is supposed to be correct except the results aren't. Thank you.

Flask request.form[] not pulling data

I am trying to post a simple html form and pull the data into python/flask. request.form does not appear to be pulling my form data.
I have a function created to pull the variables if the request method is POST, but the URL ends up with the variables being blank. See code below
#app.route('/inquire',methods=['POST','GET'])
def inquire():
if request.method == 'POST':
name = request.form['dname']
email = request.form['demail']
message = request.form['dmessage']
return
redirect(url_for('inquire_success',name=name,email=email,message=message))
return render_template('inquire.html')
#app.route('/inquiresuccess/',methods=['POST','GET'])
def inquire_success(name,email,message):
return render_template('inquiresuccess.html',name=name,email=email,message=message)
the html below :
<div class="container">
<div class="main">
<form method="post" class="form" action="{{
url_for('inquire_success' }}">
<h2>Inquire below and we'll get back to you</h2>
<label>Name :</label>
<input type="text" name="dname" id="dname" value="name">
<label>Email :</label>
<input type="text" name="demail" id="demail" value="email">
<label>Project info :</label>
<textarea class="messagebox" name="dmessage" id="dmessage"
value="message">
</textarea>
<input type="submit" name="submit" id="submit" value=Submit>
</form>
I would like the code to redirect me to inquiresuccess.html with the variables displayed. Thanks for any help.
The form looks to be posting to the wrong endpoint. Try changing
<form method="post" class="form" action="{{ url_for('inquire_success' }}">
to
<form method="post" class="form" action="{{ url_for('inquire' }}">

django ModelForms and normal form in POST request

Hi i just have a small doubt can we create a HTML template which will have the Django form and normal HTML form together.
I created a HTML template which has both normal HTML input tag and Django forms.
I am getting the following error when i do a form.save(commit=False)
could not be created because the data didn't validate.
My view.py
if request.method == 'POST':
form_value = request.POST.copy()
print form_value
form = InfoForm(data=request.POST)
post_val = form.save(commit=False)
my HTML
<div class="form-row">
<div class="form-group col-md-4">
{{form.name}}
</div>
<div class="form-group col-md-4">
{{form.number}}
</div>
<div class="form-group col-md-4">
{{form.location}}
</div>
</div>
<div class="form-group">
<label for="Feedback">Feedback</label>
<div id="Feedback" class="optionBox1">
<div class="input-group my-add-div">
<input type="text" class="form-control" name="feedback" required>
<input type="text" class="form-control" name="feedback" required>
<input type="text" class="form-control" name="feedback" required>
</div>
</div>
</div>
my form.py
class InfoForm(forms.ModelForm):
name = forms.CharField(label='Project Name',max_length=100,widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Click to enter text',}))
number = forms.DecimalField(label='Project #',widget=forms.NumberInput(attrs={'class':'form-control','placeholder':'Enter the ID',}))
location = forms.CharField(label='Location',max_length=100,widget=forms.TextInput(attrs={'class':'form-control','placeholder':'Enter the Location',}))
class Meta:
model = Info
field = ('name','number','location',)
My Model.py
name = models.CharField(max_length=200,blank=True , null=True)
number = models.IntegerField(blank=True , null=True)
location = models.CharField(max_length=200,blank=True , null=True)
feedback = ArrayField(ArrayField(models.CharField(max_length=200,blank=True,null=True)))
Thanks in advance
You need to first call form.is_valid() to use save method on the form.
All what you need to create any form in template you want, example:
``
<form action="." method="post">
{% csrf_token %}
<input type="text" name="first_name">
<p><input type='submit' value="Change"></p>
</form> ``
then, in your view call
first_name = request.POST['first_name']
and it will be works fine.

How to get the latest ID from different class in Django

I saw all the conversations about this issue, but I can't solve it. I am new in this Python-Django programming so if anyone can help me? :)
This is my views.py:
class HistoryProjectCreate(CreateView):
template_name = 'layout/create_proj_history.html'
model = ProjectHistory
project = Project.objects.latest('id')
user = User.id
fields = ['user', 'project', 'user_start_date']
success_url = reverse_lazy('git_project:index')
Var project has to return latest project ID from database, and I have to use it ID in my html form:
<form class="form-horizontal" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<label for="user"></label>
<input id="user" type="text" name="user" value="{{ user.id }}" ><br>
<label for="project">Project title: </label>
<input id="project" type="text" name="project" value="{{ project.id }}" ><br>
<!--Here - "project.id" I need latest project ID-->
<label for="user_start_date">Start date: </label>
<input id="user_start_date" type="date" name="user_start_date" value="{{ projectHistory.user_start_date }}" ><br>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-success">Submit</button>
</div>
</div>
</form>
I am not sure if project = Project.objects.latest('id') is correct statement for getting the latest ID from Project table.
If you want the last Id of project, you need to order by id, and use last() function available on queryset
project = Project.objects.order_by('id').last()
Order_by doc
Last function doc

Categories

Resources