MultiValueDictKeyError while submitting Django form - python

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

Related

Fastapi Upload a Image

i try to upload a image to a fastapi from a Cordova Webapp and get the following error:
{"detail":[{"loc":["body","terms"],"msg":"field required","type":"value_error.missing"},{"loc":["body","privacy"],"msg":"field required","type":"value_error.missing"}]}
INFO: 192.168.1.129:51915 - "POST /upload/ HTTP/1.1" 422 Unprocessable Entity
My FastApi Code is:
#app.post("/upload/", dependencies=[Depends(valid_content_length)])
async def create_upload_file(file: bytes = File(...), terms: str = Form(...), privacy: str = Form(...)):
allowedFiles = {"image/jpeg", "image/png", "image/gif", "image/tiff", "image/bmp", "video/webm"}
if file.content_type in allowedFiles:
filename = str(uuid.uuid4())
with open("uploaded_images" + filename + file.filename, "wb") as buffer:
shutil.copyfileobj(file.file, buffer)
return {"filename": file.filename}
else:
return "miau"
Client Code:
<form method="post" action="http://192.168.1.129:8080/upload">
<div class="form_row">
<label for="myfile">Choose your image:</label>
<input type="file" id="myfile" name="file">
</div>
<div class="form_row">
<label>Accept:</label>
<label class="label-checkbox item-content">
<input type="checkbox" name="my-checkbox" value="privacy" required>
<div class="item-media">
<i class="icon icon-form-checkbox"></i>
</div>
<div class="item-inner">
<div class="item-title"><a src="" target="_blank">Privacy Policy</a></div>
</div>
</label>
<label class="label-checkbox item-content">
<input type="checkbox" name="my-checkbox" value="terms" required>
<div class="item-media">
<i class="icon icon-form-checkbox"></i>
</div>
<div class="item-inner">
<div class="item-title">Terms of Use</div>
</div>
</label>
<label class="label-checkbox item-content">
<input type="submit" name="submit" class="form_submit" id="submit" value="Send"/>
</label>
</div>
</form>
How to solve the problem? According to error the body is empty, but I don't know what the problem is.
Thanks :)
The error says pretty much everything
"loc":["body","terms"],"msg":"field required"
and
"loc":["body","privacy"],"msg":"field required"
This means that your form is not submitting the terms and the privacy fields.
If you look at your HTML code, you can see that both of the inputs have the name my-checkbox, while fastapi route expects two parameters: privacy and terms.
Change the names of the inputs to match the two parameters

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

How i can get data in Python Script using Flask [duplicate]

This question already has answers here:
Post values from an HTML form and access them in a Flask view
(2 answers)
Closed 5 years ago.
I have written a html code,which will get the 3 inputs from user.
I have attached html code snippet as follows;
You can give it a try running this code. this code basically accepts 3 values from the user those are team1,team2 and match_id and upon clicking on predict button, I want those value to go in my python script where i have written machine learning algorithm.
<!DOCTYPE html>
<html>
<head>
<title>Criclytics</title>
<link rel="stylesheet" href="bootstrap.min.css">
<script src="bootstrap.min.js"></script>
<script src="jquery.min.js"></script>
<style type="text/css">
#import url(http://fonts.googleapis.com/css?family=Exo:100,200,400);
#import url(http://fonts.googleapis.com/css?family=Source+Sans+Pro:700,400,300);
body{
margin: 0;
padding: 0;
background: #fff;
color: black;
font-family: Arial;
font-size: 25px;
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
.bcg-img{
width: 100vw;
height: 100vh;
z-index: -1;
position: fixed;
background-image: url("bg-blurred.jpg");
background-position: center;
background-repeat: no-repeat;
background-size: cover;
}
table, td, th {
text-align: center;
}
table {
border-collapse: collapse;
width: 50%;
}
th, td {
padding: 15px;
}
.button1 {width: 250px;}
</style>
</head>
<body>
<div class="bcg-img"></div>
<div class="jumbotron" align="center" style="opacity:0.60">
<h1 align="center"><b>Criclytics</b></h1>
Predicting chances of winning
</div>
<form onsubmit="http://localhost:5000/">
<div class="col-xs-3">
<label for="ex2">Team 1</label>
<input class="form-control" id="team1" id="team1" type="text" placeholder="Enter team 1">
</div>
<div class="col-xs-3">
<label for="ex2">Team 2</label>
<input class="form-control" id="team2" id="team2" type="text" placeholder="Enter team 2">
</div>
<div class="col-xs-3">
<label for="ex2">Match ID:</label>
<input class="form-control" id="matchid" id="matchid" type="number" placeholder="Enter match ID ">
</div>
<br>
<input type="submit" value="Predict" class="btn btn-info btn-lg" style="width: 250px"/>
<!--
<div width="cover" padding="30%"><!--put your graph here</div>-->
</form>
</body>
</html>
I am using flask to create the server on the localhost:5000 and i have written code, as follows;
from flask import Flask, render_template
from flask import request
app = Flask(__name__)
print("hello")
#app.route('/')
def getrender():
return render_template('/cric.html')
#app.route('/',methods=['GET','POST'])
def getinfo():
if request.method == 'GET':
a=request.args.get('team1')
b=request.args.get('team2')
c=request.args.get('matchid')
print(a,b,c)
return a,b,c
if __name__=='__main__':
app.run(debug=True)
html file runs perfectly on localhost:5000 but I dont know how I can access those user input values and use it as input for my machine learining algorithm.
I just want help how to access those team1,team2 and match_id and get them in variables so that i can use them in my program.
You have a problem with your form,
all your input doesn't have a name attribute and instead it has 2 id attributes.
So change one id attribute to name
here is the reason :
Definition and Usage
The name attribute specifies the name of an element.
The name attribute is used to reference elements in a JavaScript, or
to reference form data after a form is submitted.
Note: Only form elements with a name attribute will have their values passed when submitting a form.
Your Form should be like this :
<form method="POST" action="{{url_for('getinfo')}}">
<div class="col-xs-3">
<label for="ex2">Team 1</label>
<input class="form-control" name="team1" id="team1" type="text" placeholder="Enter team 1">
</div>
<div class="col-xs-3">
<label for="ex2">Team 2</label>
<input class="form-control" name="team2" id="team2" type="text" placeholder="Enter team 2">
</div>
<div class="col-xs-3">
<label for="ex2">Match ID:</label>
<input class="form-control" id="matchid" name="matchid" type="number" placeholder="Enter match ID ">
</div>
<br>
<input type="submit" value="Predict" class="btn btn-info btn-lg" style="width: 250px"/>
<!--
<div width="cover" padding="30%"><!--put your graph here</div>-->
</form>
In your views functions, you should have 2 with different URLs: one for the home page and another for form submission
#app.route('/')
def getrender():
return render_template('/cric.html')
#app.route('/predict', methods=['GET', 'POST'])
def getinfo():
if request.method=='POST':
a=request.form.get('team1')
b=request.form.get('team2')
c=request.form.get('matchid')
print(a,b,c)
else :
return 'get Im in '
return 'OK'
My advice:
Assign another route for the html page
#app.route('/cric')
def getrender():
return render_template('/cric.html')
Update method check from GET to POST in function getinfo and use request.form to get the parameter
#app.route('/',methods=['GET','POST'])
def getinfo():
print request.method # print the request.method for debug purpose
if request.method == 'POST':
a=request.form.get('team1')
b=request.form.get('team2')
c=request.form.get('matchid')
print(a,b,c)
return render_template('/cric.html')
And update the form header and assign three input with name in html:
<form action="http://localhost:5000/" method="post">
...
<input class="form-control" id="team1" name="team1" type="text" placeholder="Enter team 1">
...
Then you can visit the '/cric' to view the html page, then submit the form, which will invoke a post request to '/' and print the parameters.

400 Bad Request (Flask + html)

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.

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