400 Bad Request (Flask + html) - python

I keep getting a 400 Bad Request when I try to run my Flask project.
I have to do a project using Flask and HTML, and it was supposed to be a group project, so members would have to learn different parts of it to then gather everything. Sadly, my 'group' didn't do anything at all
Here's my code:
Flask
app = Flask(__name__, static_url_path="")
#app.route('/', methods=['POST','GET' ]) #1 - Login e criar conta
def PagInicio():
button = request.form["button"]
if request.method == 'POST':
if button == "login":
return render_template("Princ.html")
elif button =="criar":
return render_template("Criar.html")
else:
return render_template("Inicio.html")
return render_template("Inicio.html")
HTML:
<div class="col_12">
</div>
<!-- Tab 3 - Perfil -->
<div id="tabr3" class="tab-content">
<div class="grid">
<div class="col_2"></div>
<div class="col_8">
<form class="vertical" method="POST" action="/">
<fieldset>
<div class="grid">
<div class="col_6">
<label for="usuario">Usuário</label>
<input id="usuario" name="usuario" type="text" />
</div>
<div class="col_6">
<label for="senha">Senha</label>
<input id="senha" name="senha" type="password" />
</div>
<div class="col_12 center">
<button class="medium" value="login"</i> Login</button>
</div>
<div class="col_12 center">
<button class="medium" value="criar"</i> Criar</button>
</div>
</form>
</div>
<div class="col_2"></div>
</div>
</div>
</div>
<div class="col_1"></div>
</div>

You are trying to access the request.form dictionary, always:
button = request.form["button"]
This throws a 400 response error if there is no such value in the form. This is always the case when you have a GET request, request.form is only populated when there is POST data in a valid format.
Only try to access the button when you already confirmed you have a POST request:
def PagInicio():
if request.method == 'POST':
button = request.form["button"]
if button == "login":
return render_template("Princ.html")
elif button =="criar":
return render_template("Criar.html")
else:
return render_template("Inicio.html")
return render_template("Inicio.html")
Next, you don't actually have any form element named button. You have button form elements but none have a name. Give all your buttons the same name attribute, varying the value attribute:
<div class="col_12 center">
<button class="medium" name="button" value="login"> Login</button>
</div>
<div class="col_12 center">
<button class="medium" name="button" value="criar"> Criar</button>
</div>
Note that you malformed the <button tags too.

Related

MultiValueDictKeyError while submitting Django form

I am new to Django and I am working on a site which should take user input and use it for further operations. I am using a simple text field and I am trying to access the input using request.POST method, however this is giving MultiValueDictKeyError on the name of the text field.
views.py
from django.shortcuts import render
from django.http import HttpResponse
import openpyxl
import math
def index(request):
if "GET" == request.method:
return render(request, 'index.html')
else:
excel_file = request.FILES["excel_file"]
wb = openpyxl.load_workbook(excel_file)
# getting a particular sheet by name out of many sheets
# USING TEXT BOX
sheet_id = request.POST["leadtime"]
sheet_name = str(sheet_id) + "_Day_Lead"
worksheet = wb["Observed"]
worksheet1 = wb[sheet_name]
index.html
<div class="md:flex flex-col w-full items-center">
<div class="relative mb-4">
<form action="index" method="POST">
{% csrf_token%}
<label for="full-name" class="leading-7 text-sm text-gray-600">Duration of Lead Time in Day(s)</label>
<input type="text" id="full-name" placeholder="1 to 5 or ALL" name="leadtime" class="w-full bg-white rounded border border-gray-300 focus:border-green-500 focus:ring-2 focus:ring-green-200 text-base outline-none text-gray-700 py-1 px-3 leading-8 transition-colors duration-200 ease-in-out">
</form>
</div>
<div class="relative mb-4">
<form action="index" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="file"
title="Upload excel file"
name="excel_file"
style="border: 3px solid green ; padding: 5px;"
required="required">
</div>
<button type = "submit" class="flex mx-auto text-white bg-green-500 border-0 py-2 px-8 focus:outline-none hover:bg-green-600 rounded text-lg items-center">Submit</button>
</div>
try this
sheet_id = request.POST.get("leadtime")
Refer https://docs.djangoproject.com/en/3.1/ref/request-response/#querydict-objects

How can I ask user to upload image to an html page, insert this image to an sqlite3 table using flask, and then display this image using jinja?

so far this is what I came up with
#html ask user to input information including an image
<div class="form-group">
<input autocomplete="off" autofocus class="form-control" name="name" placeholder="name" type="text">
</div>
<div class="form-group">
<input class="form-control" name="subject" placeholder="subject" type="text">
</div>
<div class="form-group">
<input class="form-control" name="experience" placeholder="experience" type="text">
</div>
<div class="form-group">
<input class="form-control" name="phone" placeholder="puone-number" type="number">
</div>
<div class="form-group">
<input type="file" name="pic" id="pic">
</div>
<button class="btn btn-primary" type="submit">Register</button>
</form>
flask
#app.route("/register", methods=["GET", "POST"])
def register():
"""Show teacher registering menu"""
if request.method == "GET":
return render_template("register.html")
else:
# get the user input
name = request.form.get("name")
sub = request.form.get("subject")
exp = request.form.get("experience")
phone = request.form.get("phone")
f = request.files['pic']
pic = f.save(secure_filename(f.filename))
if not name or not sub or not exp or not phone:
return "404"
# insert in the database
sql = "INSERT INTO teachers (name, sub, exp, phone, pic) VALUES (?, ?, ?, ?, ?)"
db.execute(sql, name, sub, exp, phone, pic)
# inform the user for the success of the process
return render_template("success.html")
showing the results on html
<div>
{% for i in query %}
<div class="media bg-primary text-white">
<img class="align-self-end mr-3" src={{ i['pic'] }} alt="Generic placeholder image">
<div class="media-body">
<h5 class="mt-0">Mr. {{ i['name'] }}</h5>
<ul class="list-group list-group-flush text-dark">
<li class="list-group-item">subject: {{ i['sub'] }},</li>
<li class="list-group-item">experience: {{ i['exp'] }},</li>
<li class="list-group-item">Contact number: {{ i['phone'] }}</li>
</ul>
</div>
</div>
<br>
{% endfor %}
</div>
but right now every time I try it I find the value of the image column in my sql table to be NULL.
How can I fix that
pic = f.save(secure_filename(f.filename))
The save method returns None, so here pic will be None.
I think you intended to write its filename to the database, so perhaps change this to:
pic = secure_filename(f.filename)
f.save(pic)
Now pic is the filename on your server, so you just need to reconstruct this wherever the file is viewed.
Of course be aware that this uses the filename of the file which was uploaded by the user. You may wish to avoid this, incase of duplicates or just for cleanliness. See this other answer I wrote regarding that.
EDIT: Regarding your template.
When it comes to loading the picture in the template, let's assume the filename came through as image.jpg, and you use your exisiting code:
<img src={{ i['pic'] }}>
You could view the source of the rendered page, and see:
<img src=image.jpg>
Two problems with this:
that attribute should have quotes (<img src="image.jpg">)
that's trying to load the file from whichever path is rendered in the browser, so if the URL was http://example.com/subdir/ it's looking for the image at http://example.com/subdir/image.jpg. This can also be verified in the Network tab of your browsers dev tools.
The solution, build the URL with flask's url_for function:
<img src="{{ url_for('static', filename=i['pic']) }}">
This, of course, assumes that you've saved the file to the static directory on your server. You may wish to ensure this in the python code:
import os
# ...
pic = secure_filename(f.filename)
f.save(os.path.join('static', pic))

get a list of values from checkboxes using flask through python

I am trying to get a list of values from checkboxes.
I found a post that looks to solve my issue (How to get if checkbox is checked on flask), however, I am continuing to receive this error: Bad Request The browser (or proxy) sent a request that this server could not understand.
I'll post my entire code block to put it in context, but without the checkboxes added, it works fine. In fact, I had the same options as a drop-down menu and it was working fine.
Please note that although I code in python on a regular basis, I am a beginner to html and flask.
<form action='/user_rec' method='POST' id='submitform'>
<input type='text', placeholder='user id' name='user_input'>
<button type="submit" class="btn btn-success">Recommend</button>
<br><br>
<h2>Other Options</h2>
<h5>Best Number of Players</h5>
<div class="checkbox">
<label><input type="checkbox" name="check" value="1">1</label>
</div>
<div class="checkbox">
<label><input type="checkbox" name="check" value="2">2</label>
</div>
<div class="checkbox">
<label><input type="checkbox" name="check" value="3">3</label>
</div>
<div class="checkbox">
<label><input type="checkbox" name="check" value="4">4</label>
</div>
<div class="checkbox">
<label><input type="checkbox" name="check" value="5">5+</label>
</div>
<h5>Minimum Play Time (minutes)</h5>
<input type="text", placeholder='0' name='min_time'>
<br><br>
<h5>Maximum Play Time (minutes)</h5>
<input type="text", placeholder='500000' name='max_time'>
</form>
and my python code:
#app.route('/user_rec', methods=['POST'])
def button1():
user_name = (request.form['user_input'])
best_num_player = (request.form['best_num_player'])
min_time = (request.form['min_time'])
max_time = (request.form['max_time'])
players = request.form.getlist('check')
I think there are two problems with your code:
'best_num_player' is not a key in the form dict.
You didn't return a redirect after posting.
Here's an example app.py that you can try. (I assumed you named the template index.html)
from flask import Flask, render_template, redirect, request
app = Flask(__name__)
#app.route('/')
def index():
return render_template('index.html')
#app.route('/user_rec', methods=['POST'])
def user_rec():
user_name = request.form.get('user_input')
min_time = request.form.get('min_time')
max_time = request.form.get('max_time')
players = request.form.getlist('check')
print(user_name, min_time, max_time, players)
return redirect('/')
if __name__ == '__main__':
app.run(debug=True)

Send data from django views to angularjs controller

I am trying to send data from django views.py file to angularjs controller.js file but unable to send it.
The problem is this that I am unable to send data from views file to controller. And when I run my code then the value {%steps%} doesn't change to the value I have assigned in views file.
I don't want to use Django rest framework for doing this.
Is there any other way of achieving this? If yes, then please help me out.
views.py:
from django.shortcuts import render
from django.conf import settings
from user_data.models import GetData
import json
def home(req):
return render(req, 'index.html')
def userData(req):
if req.method == 'GET':
user_data = GetData().getAllData()
context_dict = {'user_data1' : json.dumps(user_data[0]),
'user_data2' : json.dumps(user_data[1]),
'user_steps' : json.dumps(2000)}
return render(req, 'index.html', context_dict)
controller.js :
'use strict';
MetronicApp.controller('DashboardController', function($rootScope, $scope, $http, $timeout) {
$scope.$on('$viewContentLoaded', function() {
// initialize core components
Metronic.initAjax();
});
$scope.steps = {{user_steps|safe}};
});
html file:-
<div ng-controller="DashboardController" class="margin-top-10">
<div class="row ">
<div class="col-md-12 col-sm-12">
<div class="portlet light ">
<div class="portlet-title">
<div class="caption">
<i class="icon-cursor font-purple-intense hide"></i>
<span class="caption-subject font-purple-intense bold uppercase">Tracker Report</span>
</div>
<div class="actions">
<a href="javascript:;" class="btn btn-sm btn-circle btn-default easy-pie-chart-reload">
<i class="fa fa-repeat"></i> Reload </a>
</div>
</div>
<div class="portlet-body">
<div class="row">
<div class="col-md-3">
<div class="easy-pie-chart">
<div class="number transactions" data-percent="55">
<span>{$ steps $}</span>
</div>
<!-- <a class="title" href="#"> -->
Steps <!-- <i class="icon-arrow-right"></i> -->
</a>
</div>
</div>
<div class="margin-bottom-10 visible-sm">
</div>
<div class="col-md-3">
<div class="easy-pie-chart">
<div class="number visits" data-percent="85">
<span>
+85 </span>
%
</div>
<!-- <a class="title" href="#"> -->
Sleep<!-- <i class="icon-arrow-right"></i> -->
</a>
</div>
</div>
<div class="margin-bottom-10 visible-sm">
</div>
<div class="col-md-3">
<div class="easy-pie-chart">
<div class="number bounce" data-percent="46">
<span>
+46 </span>
%
</div>
<!-- <a class="title" href="#"> -->
Calories <!-- <i class="icon-arrow-right"></i> -->
</a>
</div>
</div>
<div class="margin-bottom-10 visible-sm">
</div>
<div class="col-md-3">
<div class="easy-pie-chart">
<div class="number bounce" data-percent="32">
<span>
+32 </span>
%
</div>
</a>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
This is basically what I have done in one of my major django projects (but I am not 100% sure, whether this is or this ain't what you are looking for, as an answer).
So, instead of views.py, I have made a custom.py file in which I make custom APIs and call them (using urlpatterns) in the urls.py of my django app. And I have another set of APIs for which I am using django rest framework, for which I make viewsets rather than simple views. Just in case, you are interested, you might like reading this SO link.
But since, you specifically mentioned that you don't want to use django rest frameworks, I will give you an example of the custom.py file, as mentioned above.
Below you will find a sample of an API defined in a custom.py,
#api_view(['GET'])
def get_user_details(request):
"""
API View that gives a user detail
---
parameters:
- name: email
description: The email of the user based on which his/her information has been extracted
required: true
type: string
responseMessages:
- code: 400
message: Email required as GET parameters.
message: User not found.
- code: 200
mesage: User details sent successfully
consumes:
- application/json
- application/xml
produces:
- application/json
- application/xml
"""
email = request.query_params.get('email', None)
if email is None:
return HttpResponseBadRequest("Email required as GET parameters.")
try:
user = User.objects.get(username=email)
except User.DoesNotExist:
return HttpResponseBadRequest("User not found.")
response_data = {'id': user.id, 'first_name': user.first_name, 'last_name': user.last_name,}
return HttpResponse(json.dumps(response_data), content_type="application/json")
And subsequently, the urls.py in my django app looks like:
urlpatterns = router.urls
urlpatterns = urlpatterns + [
url(r'get_user_details/', get_user_details),
]
My controller would look something like this:
CheckEmail : function (current) {
return $http({
method: 'GET',
url: baseAPI + 'admin/get_user_details/',
params: {email: current},
})
},
And then subsequently, you may be able to render the variable you wish to print in your html file using handles.
Hope, it helps.

Check if the user's input is valid

Users are entering their address and age. When the find button is hit, it will display the inputs. However, for the case where input is not valid, I would like to add an error message.
How do I check if the input is not valid and gives an error message? I want my error message to be on the same page as where values are input. The code does not work correctly.
<div class = "Information">
<h2>Your Infomation</h2>
<form action="" method=post>
if (error){
<p id="error"><strong></strong>{{error}}
}
<div id = "address">
<label>address</label>
<input type=text name=address value="{{request.form.address}}">
</div>
<div id = "age">
<label>age</label>
<input type=text name=age value="{{request.form.age}}">
</div>
<div class = "Input">
<a href="/results">
<button type = "button" class = "btn btn-primary" value="find" >Find!</button>
</a>
</div>
</form>
</div>
#app.route('/results',methods=['GET','POST'])
def result():
error = None;
if request.method == 'POST':
if request.form['age'] != '14':
error='You did not enter proper values'
return render_template('template.html',error=error)
You need to use proper Jinja syntax to render templates:
{% if error %}<p id="error">{{ error }}</p>{% endif %}
Beyond that, the button you've added to your form doesn't actually submit the form, as you've given it the "button" type rather than the "submit" type and have wrapped it in an anchor for some reason. Replace the contents of <div class="Input"> with:
<button type="submit" class="btn btn-primary" value="find">Find!</button>

Categories