I am working with dynamic data that requires an ID and a year to load, both of which are input by the user. The ID is unique, so two users will very likely be looking at different data. They are passed into a URL that returns a large dictionary. This dictionary is then passed to a bunch of other functions for various analyses and visuals. I was thinking of displaying the data in its own hidden route and have other routes call on it (I am new to flask, so there could be a better/more efficient way of storing and accessing dynamic data like this).
Here is the flask code to display the form and where I try to access the data:
#app.route("/")
def home():
return render_template("index.html")
#app.route("/data/<lid>/<ssn>", methods=["GET","POST"])
def data_league():
if request.method == "POST":
league_id = request.form["lid"]
season = request.form["ssn"]
url = 'http://fantasy.espn.com/apis/v3/games/ffl/seasons/' + season + '/segments/0/leagues/' + league_id + '?view=mMatchupScore&view=mTeam&view=mSettings'
r = requests.get(url,
params={'view':'mMatchup'})
d = r.json()
return d
And the HTML code that creates the form:
<form class="row row-cols-lg-auto g-3 align-items-center" action="#" method="post" style="margin-
left: 180px;">
<div class="col-5">
<label class="visually-hidden" for="league_id">Username</label>
<div class="input-group">
<input type="text" class="form-control" name="lid" id="lId" placeholder="League ID">
</div>
</div>
<div class="col-5">
<label class="visually-hidden" for="season">Preference</label>
<select class="form-select" name="ssn" id="Ssn">
<option selected>Select a Season</option>
<option value="1">2020</option>
<option value="2">2019</option>
<option value="3">2018</option>
</select>
</div>
<div class="col-12">
<button type="submit" class="btn btn-primary">Submit</button>
</div>
</form>
When I run the app and input an ID and year, I get a TypeError saying that "data_league() got an unexpected keyword argument 'lid'". What am I doing wrong?
Related
The purpose of this piece of code is to ask users to input a specific date and time. The input should be sent from the HTML form to app.py, and the python script should check the input and display "available stalls" accordingly.
I tried this:
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<div class="box-header">
<h3 class="box-title">Please select a date & time to view available stalls : </h3>
</div>
<div class="box-body">
<form method="POST" action="">
<div class="form-group">
<label>Date and time range:</label>
<div class="input-group">
*****<input type="datetime-local" id="reservationtime"
name="reservationtime" value="2019-11-15T14:30"
min="2019-01-01T00:00" max="2030-12-31T00:00">*****
</div>
<button type = "submit" class="btn btn-primary">Submit</button>
<!-- /.input group -->
</div>
</form>
</div>
</div>
</div>
</div>
the python code is:
resultstruct_time = time.strptime(reservationtime,"%Y-%m-%d %H:%M")
reservationDayID = resultstruct_time(6) + 1
reservationHour = resultstruct_time(3)
And the error I have been getting is:
TypeError: strptime() argument 0 must be str, not class 'NoneType'
Could anyone help me solve this problem by telling me how to change the input into str while keeping the input type as "datetime-local?" Thank you!
Edit: It seems that the HTML form is returning nothing to python. But why does that happen? Is there any way to pass back the desired value of "reservationtime?" Here's a repost of all the relevant code down below:
python:
#app.route("/FilterStallsPage",methods = ["GET","POST"])
def DisplayFilterStallsPage():
stallsInfoDict, availableStallsCount = filterAvailableStalls()
return render_template('FilterStallsPage.html',stallsInfoDict = stallsInfoDict, \
totalStalls = len(stallsInfoDict), availableStalls = availableStallsCount)
def getReservationTime():
if request.method == "POST":
reservationtime = request.form["reservationtime"]
return reservationtime
def filterAvailableStalls():
reservationtime = getReservationTime()
resultstruct_time = time.strptime(str(reservationtime),"%Y-%m-%d %H:%M")
reservationDayID = resultstruct_time(6) + 1
reservationHour = resultstruct_time(3)
(the rest block of irrelevant code not included)
HTML:
<div class="row">
<div class="col-md-12">
<div class="box box-primary">
<div class="box-header">
<h3 class="box-title">Please select a date & time to view available stalls : </h3>
</div>
<div class="box-body">
<form method="POST" action="">
<div class="form-group">
<label>Date and time range:</label>
<div class="input-group">
*****<input type="datetime-local" id="reservationtime"
name="reservationtime" value="2019-11-15T14:30"
min="2019-01-01T00:00" max="2030-12-31T00:00">*****
</div>
<button type = "submit" class="btn btn-primary">Submit</button>
<!-- /.input group -->
</div>
</form>
</div>
</div>
</div>
</div>
Thank you!
I'm guessing nothing is being returned. You could try adding print at the place where the python receives the response. Print type of the response received then start debugging from there. Try type casting to string. Try checking if nothing is returned. Sometimes nothing is returned and its a noneType object.
print(type(reservationtime) ) #debugging
print(reservationtime) #debugging
resultstruct_time = time.strptime(str(reservationtime),"%Y-%m-%d %H:%M")
edit-helping-debug
def getReservationTime():
if request.method == "POST":
print('made to POST')
return "test-string"
#reservationtime = request.form["reservationtime"]
#return reservationtime
okay if you get the print and it doesn't return a noneType it means you only have to fix the commented lines.
If it doesn't make it there you have to fix the get reservation code that handles generating the post. I haven't worked with flask enough to give you the exact answer just keep fiddling with it and see wether a post request is even occurring.
Getting a 400, when trying to upload a file ad send other form elements to flask from html. Tried to use ajax, but that throws me an error as well.
Python:
#app.route('/prod_diff_result', methods=['POST', 'GET'])
def prod_diff_result():
try:
host = request.form['host-prod-iterator']
print(host)
if request.files['file']:
f = request.files['file']
f.save(secure_filename(f.filename))
HTML:
<div class="main-div">
<form action="/prod_diff_result" method="POST" enctype="multipart/form-data">
<div class="grid-container">
<div class="grid-item">
<span class="label label-default ">PROD</span><br>
<p>Iterator Host : <input type="text" class="form-control" id="host-prod-iterator" value="10.47.7.57"
required></p>
<input type="radio" name="data_fetch_type" value="file" onclick="showfile()">Upload File
<input type="file" name="file" />
<input type="radio" name="data_fetch_type" value="db"> Get from DB
<input type="submit" />
</div>
</form>
</div>
I want to be able send hostname and file back to flask error in one request and using one form.
It gives an error because you try to access a form field that it cannot find, and assumes that somehow the request was bad, because it didn't include a required form field. You are trying to access:
host = request.form['host-prod-iterator']
However you have simply not given it a name in your HTML. If you give it a name, it should work:
<p>Iterator Host :
<input type="text" class="form-control" name="host-prod-iterator" id="host-prod-iterator" value="10.47.7.57" required>
</p>
I am attempting to return data from a HTML form with a POST request using Flask. For some reason I get a 400 Bad Request error. Looking at Chrome Dev Tools, I can see that all of the form fields with the input tag are part of the post request. The select tag with the dropwdown list is not being captured and I think this is creating the error. Anyone know why the select tag is not being captured in the post request? Any help much appreciated.
Here is the HTML form:
<label for="vendor">Select Vendor</label>
<div class="flextable p-b" style="padd">
<div class="flextable-item">
<select class="selectpicker" data-live-search="true" form="addInvoice" name="vendor" id="vendor">
<option>Jack Jaffa & Associates</option>
<option>Jacobs/Doland/Beer LLC</option>
<option>Jenkins & Huntington Inc.</option>
<option>Joseph J. Blake & Associates, Inc.</option>
<option>Langan (Geotechnical)</option>
<option>Madison Realty Capital</option>
<option>McNamara Salvia, Inc</option>
<option>Metropolis Group, Inc</option>
<option>National Grid</option>
</select>
</div>
<div class="flextable-item">
<button type="button" class="btn btn-xs btn-primary-outline">Add vendor</button>
</div>
<label for="invoice_number">Invoice Number:</label>
<input type="text" class="form-control p-b" placeholder="Every vendor invoice # must be unique" name="invoice_number" id="invoice_number">
<label for="invoice_amount">Amount:</label>
<input type="text" class="form-control p-b" placeholder="$0.00" name="invoice_amount" id="invoice_amount">
<label for="invoice_amount">Description:</label>
<input type="text" class="form-control p-b" placeholder="$0.00" width="100%" name="description" id="description">
<div class="spacer"></div>
<div class="flextable">
<div class="flextable-item">
<label for="date_received">Date received:</label>
</div>
<div>
<div class="flextable-item">
<div class="input-group">
<span class="input-group-addon">
<span class="icon icon-calendar"></span>
</span>
<input type="text" value="01/01/2015" class="form-control" data-provide="datepicker" style="width: 200px;" name="date_received" id="date_received">
</div>
</div>
</div>
</div>
</div>
<div class="modal-actions p-t-lg">
<button type="button" class="btn-link modal-action" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn-link modal-action" id="submit" >
<strong>Save + Continue</strong>
</button>
</div>
</form>
Here is the Flask python route:
#app.route('/add_invoice', methods=['GET', 'POST'])
def add_invoice():
""" Method for capturing form data to add invoice items to database"""
if request.method == 'POST':
find_cost_code = 7777 # eventually need code to lookup cost-code from POST request
print request.form['invoice_number']
print request.form['invoice_amount']
print request.form['description']
print request.form['vendor']
print request.form['date_received']
return "This is a test"
ADDED INFO:
So if I remove this line, the bad request error goes away:
print request.form['vendor']
This is because the "vendor" field is the only one in the html form that uses a select tag for input and that data is not catpured in the post request dictionary (which i can see in Chrome Dev Tool). The POST request is missing the field associated with the select tag. Not sure how to capture the select tag in the form data...
I've faced this issue many time when dealing with flask form, I think the solution is to enable csrf token protection :
according to this you need to initialise and enable it for you app!
Most of time error 400 is due to missing CSRF token.
you can do it as :
from flask_wtf.csrf import CSRFProtect
csrf = CSRFProtect(app)
for initialisation
and in your form add:
<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>
hope it will help!!
feel free to edit.
form="addInvoice"
This attribute as part of my HTML form markup was what caused the error. I'm not sure exactly why but when it is removed, the error goes away.
(Thanks for your help above in trying to look into this.)
You need getlist to capture select.
I tried to used bootstrap-select whith the following example, but in Flask I get only one value and not the maximum two values?
<form class="form-horizontal" action="{{url_for('compare')}}" method="get" role="form">
<div class="input-group">
<span class="input-group-addon">Tests:</span>
<select name='tests' class="selectpicker show-menu-arrow form-control" multiple data-max-options="2" data-live-search="true">
<option value="Test1">Test1</option>
<option value="Test2">Test2</option>
<option value="Test3">Test3</option>
</select>
<span class="input-group-btn">
<button class="btn btn-default" type="submit">Search!</button>
</span>
</div>
</form>
<hr>
The route in Flask is define like below:
#app.route("/compare/", methods=["GET"])
#templated('compare.tmpl')
def compare():
tests = request.args.get('tests')
How is it possible to get maximum two selected values in flask e.g. Test1 and Test2?
request.args is a MultiDict. It provides a method called getlist that will return a list of items for the given key rather than a single value. Update your code to the following.
tests = request.args.getlist('tests')
More information can be found in the werkzeug documentation.
This is the Html form:
<form action='use.py'>
<div><input type='text' name='etc'></div>
<p><input type='submit' value='etc!'></p>
</form>
And this is the python for it
colour = form["colour"].value
The top html form is a text box that users can type something in.
If I were to have a drop down box / radio button form like this:
<form action='etc.py'>
<p>List Type:</p>
<div><input type='radio' name='status' value='bulleted' checked>
Bulleted
</div>
<div><input type='radio' name='status' value='numbered'>
Numbered
</div>
<p>Text style:</p>
<div><input type='checkbox' name='bold'>
<b>Bold</b>
</div>
<div><input type='checkbox' name='italic'>
<i>Italic</i>
</div>
<p>Movies to display:</p>
<div>
<select name='type'>
<option>Only numbers</option>
<option>Only names</option>
</select>
</div>
<p><input type='submit' value='Display'></p>
</form>
How would I write my python? Like this?
only_numbers = form["Only numbers"].value
You can write a Python CGI script, but most Python frameworks are built upon WSGI and have a concept of request/response objects. For example, in Django the value would be available at request.POST['fieldname'].
Using the python CGI module, it is like:
form = cgi.FieldStorage()
# for multiple elements with same name or elements with multiple values
a_list = form.getlist("multiple_select_input")
# For single value elements
if "single_value_input" in form:
x = form["single_value_input"].value
else:
x = "default value"
# or
x = form.getvalue("single_value_input", "default value")