Web2py: How to get items in FieldStorage? - python

I have a form that accepts image uploads:
<form name="upload" enctype="multipart/form-data" method="post" class="form-horizontal">
<div class="control-group">
<div class="span2">
<label for="image" class="control-label">Upload image:</label>
</div>
<div class="span10">
<input id="image" name="image" type="file" class="span7" accept="image/*"/>
</div>
</div>
<div class="form-group">
<div class="span2"></div>
<div class="span10">
<button class="btn btn-medium btn-primary" type="submit">Submit</button>
</div>
</div>
</form>
When I request.vars['image'], the following is returned:
FieldStorage('image', 'a.png', '\x89PNG\r\n\x1a\n\x00...')
How do I access these items? If I attempt to work with it as I would a dict, I receive an error that the object is not indexable. I've never worked with FieldStorage before, so I'm not exactly sure what I need to do to access this data.

If anyone else is interested, this worked:
request.vars['image'].filename
request.vars['image'].value
For the file name and binary data, respectively. Just needed a quick summary of the available attributes: http://python.about.com/od/cgiformswithpython/ss/pycgitut1_3.htm

This is extremely helpful if you are trying to check some aspects of a file before trying to process a form. I wanted to get the sha256 hash of an uploaded file and make sure it hadn't been uploaded before. The upload is in a field Field('file', 'upload').
Originally, I used the following, but this consumes the data in request.vars.file so that, after successful processing, the file written to disk is empty.
file_contents = request.vars.file.read()
form.vars.file_hash = hashlib.sha256(file_contents).hexdigest()
form.vars.file_length = len(file_contents)
However, in the updated code below datasci's answer allows you to access the data without consuming it from request.vars.file. Might be obvious, but it took a long time for me to figure out what was going on!
# Is there a file - the value will be None when the page first loads and
# can be 'str' if submit is pressed without a file selected.
if request.vars.file != None and not isinstance(request.vars.file, str):
form.vars.file_name = request.vars.file.filename
form.vars.file_hash = hashlib.sha256(request.vars.file.value).hexdigest()
form.vars.file_size= len(request.vars.file.value)
if form.process(onvalidation=validate_dataset_upload).accepted:
# notify upload has worked
response.flash = ('Upload successful. A validation check will be run and '
'you will get an email with the results when it finishes.')
All of this means that the validate_dataset_upload function can now check form.vars.file_hash does not already exist in the underlying table.

Related

Sending a POST request to python function via an HTML form

I am absolutely new to HTML and I was wondering if Someone could help me out. I tried looking for similar questions as mine but I didn't find anything quite like what I am looking for. Sorry if this question seems dumb or easy to you I am trying to learn! So basically I have an ID that I can access inside of my HTML file and I want to send it to my python function through a form, I have already managed to do this for buttons but never for a form. This is how I would send my ID to my function with a button:
<a href="{{url_for('validate_comment', item_id=msr.id)}}"> <--- the msr.id is my ID
<button type="button">
<div class="font-weight-bold">Ajouter un commentaire</div>
</button>
</a>
And this works perfectly but i was wondering if there was any way to do the same with a form as I am not calling a function but doing an action instead. This is how my form looks:
<form id="commentaire_form" method="post" action="/testement"> <--- here is where I give the route but how can i send the ID to the function linked to this route?
<textarea id='text' name="text"></textarea>
<input type="submit">
</form>
If anyone could help me I would greatly appreciate it, thanks in advance :-)
The below will make a POST request to the /testement route/URL. You can catch the id POST value in your python script.
<form id="commentaire_form" method="post" action="/testement">
<textarea id='text' name="text"></textarea>
<input type="hidden" name="id" value="{{ msr.id }}">
<input type="submit">
</form>

FLASK app: Sending data from a Form through another script while one "input" is a dynamic paragraph

I have a from with three possible inputs to submit and send through a seperate script that then generates JSON data.
The problem is however while two inputs are actual inputs = one email and one being a nummer. The third one is not a really traditional input.
<form action="{ url_for('handle_data') }}" method="POST">
<div class="form-group">
<label for="Speryear">SPER jaar</label>
<input class="form-control" type="number" value="2" name="Speryear" min=0 max=10 />
</div>
<div class="form-group">
<div class="form-group">
<label for="inputEmail">Verzendings mail</label>
<input class="form-control" type="email" name="inputEmail" required />
</div>
</div>
<div class="form-group">
<div class="url-panel">
<p> <b>Url:</b></p>
<p id="api-url" name="api-url"></p>
</div>
</div>
<button id="search" type="submit" class="btn-primary">
Aanvraag indienen</button>
</form>
#app.route('/handle_data', methods=['POST'])
def handle_data():
sper_year = request.form["Speryear"]
email = request.form["inputEmail"]
url = request.form["api-url"]
Requested_data = GIPOD_converter.main(url, sper_year, email)
return Requested_data
The third input is actually a paragraph which is dynamically based on the values of a second form (the primary from) for the data requests. According to this post here:
Sending data from a html non-input to Flask
HTML forms only send along tagged values to the remote endpoint when a "submit" input is pressed.
I have tried to make this paragraph a data input but the thing is this will break the javascript I have for that specific id. Aka a the URL part that I want cannot be generated in the input field. So can my code get the paragraph from this?
Edits done as per answer.
I think you should end the app route with:
return Requested_data
Also, you do not define correctly to the url form, i.e.:
url = request.form["api-url"]

Python Flask: Bad Request on Post method with radio-option checked

Lets say I have 2 radio buttons in my html script, of which one is checked by default:
<form action="" method="post">
<div class="radio-option checked">
<input type="radio" name="radioName" value="val_1"/>
</div>
<div class="radio-option">
<input type="radio" name="radioName" value="val_2"/>
</div>
<div>
<input type="submit" value="Confirm and continue"/>
</div>
</form>
If I click the submit button without clicking the other radio button, I get an error:
Bad Request The browser (or proxy) sent a request that this server
could not understand.
This happens because there is no value which is being transfered if a radio button is checked by default but not being selected with the mouse afterwards! This is what request.form shows me ImmutableMultiDict([]). If I select the other radio button with the mouse and click the submit button it shows me values ImmutableMultiDict(['radioName', 'val_2'])
I tried to catch the error like this, but it didn't work out:
if request.form == '':
flash('error')
return render_template('default_template.html')
How can I handle this within flask?
How can I set a default value, which can be sent to the server?
You could perform a check within flask. Check if request.form has items or if its empty and throw the error in that case.
A simple way of knowing if its empty would be, for example:
if len(request.form) == 0:
print('Error: The form is empty')
else:
print('The form has data, we can proceed')
Another way is:
if 'radioName' not in request.form:
print('Error: The form is empty')
...
But maybe flask has a better way of doing this or there are better practices to follow in these cases.
On the other hand, in the html snippet that you posted, none of the inputs is checked by default.
You have the checked css class on a div but not the checked attribute in an input with type=radio.
The correct use of checked attribute would be as follows:
<form action="" method="post">
<div class="radio-option checked">
<input type="radio" name="radioName" value="val_1" checked/>
</div>
<div class="radio-option">
<input type="radio" name="radioName" value="val_2"/>
</div>
<div>
<input type="submit" value="Confirm and continue"/>
</div>
</form>
This way, the radio input with value val_1, will be checked by default, populating the dictionary that goes to the server.
For more information, check out: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/radio
You can also avoid sending empty forms to the server using the required attribute to make sure that the user fills the form as expected.
To learn more about this: https://developer.mozilla.org/en-US/docs/Learn/HTML/Forms/Form_validation
I hope it helps!

Serve a file based on request parameters in tornado

The problem looks simple but everywhere I search it I get results for uploading a file, whereas my use case is, that based on a few params, I in my Handler decide the relevant file and upload it as a link in my View. I am using tornado for this. e.g :
<div class="form-group"> <!-- Date input -->
<label for="actDateFrom" class="control-label">Date</label>
<input ng-model="data.actDateFrom" class="form-control" name="actDateFrom" placeholder="MM/DD/YYY" type="text"/>
</div>
<div class="form-group"> <!-- Date input -->
<label for="actDateTo" class="control-label">Date</label>
<input ng-model="data.actDateTo" class="form-control" name="actDateTo" placeholder="MM/DD/YYY" type="text"/>
</div>
<div class="form-group"> <!-- Submit button -->
<button type="submit" class="btn btn-default" data-ng-disabled="form.$invalid" data-ng-click="sendActRequest()" >Go Fetch !</button>
</div>
Based on the inputs above, I have a handler, that should basically filter a csv file and get that file showing up as a link .
All I am stuck at is the code for uploading that subset file as a link in my view, I can manage the rest. Please not that the file is lying somewhere on the server itself.
Thanks in Advance!
Lol that was so easy, I think the funda is that only a static file can be served, I just put it in my some web/static/files path which is visible to the server and posted a href link to it, something like below:
<div>
Activations Logs for the time period.
</div>
Please dont downvote, actually I am new to Web Dev :P Thanks !

Sending data to server flask html

I am trying to create a simple checkbox that sends the data to server here is my html code.
<form action="." method="POST">
<div class="checksheet">
<input id="XML Parser" class="checkbox" type="checkbox"/>XML Parser
<input id="Feed Parser" class="checkbox" type="checkbox"/>Feed Parser
<input id="Text Parser" class="checkbox" type="checkbox"/>Text Parser
<input id="Case Normalization" class="checkbox" type="checkbox"/>Case Normalization
<input id="Stemmer" class="checkbox" type="checkbox"/> Stemmer
</div>
<div class="submit"><input type="submit" value="Send" name="raw_text"></div>
</form>
What I am trying to do is very similar to the question asked here: Send Data from a textbox into Flask?
But except with the text box.. I have checkboxes.
But I get this error:
Not Found
The requested URL was not found on the server.
If you entered the URL manually please check your spelling and try again.
MY server side code (in flask) is:
#app.route('/raw_text.html')
def home ():
file = "sample.xml"
contents = open(file).read()
contents = contents.decode('utf-8')
return render_template('raw_text.html', contents=contents,file=file)
#app.route('/raw_text.html',methods=['POST'])
def get_data():
print "REQUEST ",request.form()
data = request.form['raw_text']
print data
return "Processed"
Any suggestions.
Thanks
A few things:
Your checkbox elements need a name attribute, this is what is used when the data is sent to the back end. Each checkbox that is related to each other needs to have the same name.
Your action attribute needs to point to a URL. If you are posting it to the same page as the form, you can remove the attribute.
ID's cannot contain spaces.
To be accessible the check boxes need <label>s,

Categories