python flask iframe and download - python

I have to perform two actions based on radio button selection, either download or view a document
<form method="post" action="{{ url_for('page_after_submit') }}">
<p> Your resume </p>
<div class="radio">
<label> <input type="radio" name="optionsRadios" id="optionsRadios1" value="option1" checked> Download document </label>
</div>
<div class="radio">
<label> <input type="radio" name="optionsRadios" id="optionsRadios2" value="option2"> View document </label>
</div>
<input type="submit" />
</form>
My page_after_submit has this code...
#app.route(local.URL_PREFIX + '/page_after_submit/', methods=['POST'])
def after_submit():
if 'option1' == request.form['optionsRadios']:
return/redirect ("download from this url")
if 'option2' == request.form['optionsRadios']:
return/redirect ("view in this iframe")
return (Url_for('go back to submit page if you are here')
I know my form can only have one action which is '/page_after_submit/', what code (HTML or Python in flask) I need to complete rest of my actions ??? I tried to put the iframe tags with complete download file address in the redirect for option2 but doesn't work. I also want this iframe to pop up not open a new browser window. Plus for the download, don't know what to do specially different operating system may have different path for download directory.
My goal is to not have any javascript as well, don't know if it's possible or not. Thanks in advance.

You need to craft a different response depending on how they want to see the data.
Download File
If they choose option 1, you need to set the headers and response to allow the browser to trigger a file download. Here's how you can do something like that.
View File in Iframe
If they choose option 2, you need to return an HTML response which loads the file. This can be done in an Iframe if you'd like, but it's not necessary. Here's one possible way to do that, but many others exist.

Related

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!

Django/Python: Pulling value from template into views.py

I currently have a search function in my views.py file like so:
def json_search(request):
query = request.GET.get('query')
api_key = locu_api
url = 'https://api.locu.com/v1_0/venue/search/?api_key=' + api_key
locality = query.replace(' ', '%20')
category =
final_url = url + "&locality=" + locality + "&category=" + category
json_obj = urllib2.urlopen(final_url)
decoded_data = json.load(json_obj)
return render(request, 'loc_search.html',
{'objects': decoded_data['objects']})
What I have set up is a drop-down search bar whereby I want the category variable within my json_search() function to automatically be assigned to the selected option on the drop-down bar before the form is submitted using the submit button. The search bar looks like this :
And the code like this:
<form action="{% url 'search' %}">
<div class="input-group">
<input name="query" input id="address" type="textbox" placeholder="City or Zipcode" class="form-control datebox">
<div class="input-group-btn">
<button class="btn btn-default" type="submit" id="addressSearch">Search</button>
<button name = "category_query" tabindex="-3" data-toggle="dropdown" class="btn btn-default dropdown-toggle" type="button">
<span class="caret"></span>
<span class="sr-only">Toggle Dropdown</span>
</button>
<ul class="dropdown-menu" >
<li>Resturant</li>
<li>Activities</li>
<li>Bar / Club</li>
<li class="divider"></li>
<li>other</li>
</ul>
</div>
</div>
</form>
Is this even possible?
You would have to get the value back to the backend view code in some fashion in order for that to happen.
It would be possible to do so prior submitting the form. For example, you could use an Ajax call within the template code to hit the same URL serviced by the json_search function, passing category in the URL, and then pulling it out of request.GET.
If you wanted it to be assigned upon dropdown selection, you would want to attach a click event handler via jQuery to that dropdown, and then in that handler's function, get the selected value, and then add it to the Ajax call back to your json_search function.
In your json_search code, you'll want to differentiate handling the submit (which should be a POST) vs. general GET handling (perhaps based on whether various parameters are present in the URL).
Edit in response to comment from OP:
It's certainly not trivial, especially if you've not worked with Ajax before, but it shouldn't be too bad overall (and once you get the hang of it, this paradigm can be used for all sorts of interaction with other modules like Datatables and many others, not to mention your own Django backend).
While there are many different ways to do this, I'm a fan of using jQuery's when in conjunction with done (used in examples on the same page). The when lets you fire off multiple asynchronous Ajax requests, and the done acts as a join point where you wait for them to finish before proceeding.
Yes, this is possible, you would make all the links in the dropdown have a onclick handler which would need to save the category. Then instead of a url for the form you would use a submit function which would send your form data + the category.
That is something easy to do with angular + ui.bootstrap.
with jQuery
http://plnkr.co/edit/iBY2n9dq8Tn95IUGwNAB?p=preview
You need to transform your links not to have a valid href and instead call a function, e.g.:
Restaurant
and add a hidden field for the category
<input name="category" input="" id="category" type="hidden" placeholder="Category" class="form-control" />
and some easy javascript
function setCategory(category) {
alert('category (hidden) = ' + category);
$('#category').val(category);
}

Selecting form input with Selenium isn't working?

I was making an software which should connect to website using Selenium (firefox, python) and click "Yes" button. Here's page's source code (just that form part):
<div class="grid_24">
<div class="content_block">
<form action="" method="POST" class="fatform">
<p style="text-align:center;">
<input style="margin-right:50px;float:none;" type="submit" name="yes" value="da">
<input style="float:none;" type="submit" name="no" value="ne">
<input type="hidden" name="checkthis" value="lpftvqenq">
</p>
</form>
</div>
I was looking at Selenium Python Docs but I couldn't solve it by myself. So I'm here. I tried few types of selecting elements like this:
proxy(ip, port).find_element_by_name('yes').click()
form = proxy(ip, port).find_elements_by_class_name("fatform") #printing this gives nothing
proxy(ip, port).find_element_by_css_selector(".yes[value='da']").click()
All these examples (except form string which returns "") return NoSuchElementException.
Thanks in advance! :)
Why not search for the element by xpath instead? From my experience, the XPath generated by the Firebug add-in for Firefox works extremely well for me.
proxy(ip, port).find_element_by_xpath("xpath text").click()
You are using wrong selector.
. in css selector means class which is not the case here. Should look like
[name='yes'][value='da']
EDIT
Including explicit wait
WebDriverWait(proxy(ip, port), 10).until(
EC.find_element_by_css_selector((By.CSS_SELECTOR, "[name='yes'][value='da']"))
proxy(ip, port).find_element_by_css_selector("[name='yes'][value='da']").click()

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,

Using Urllib instead of action in post form

I need to allow users to upload content directly to Amazon S3. This form works:
<form action="https://me.s3.amazonaws.com/" method="post" enctype='multipart/form-data' class="upload-form">{% csrf_token %}
<input type="hidden" name="key" value="videos/test.jpg">
<input type="hidden" name="AWSAccessKeyId" value="<access_key>">
<input type="hidden" name="acl" value="public-read">
<input type="hidden" name="policy" value="{{policy}}">
<input type="hidden" name="signature" value="{{signature}}">
<input type="hidden" name="Content-Type" value="image/jpeg">
<input type="submit" value="Upload" name="upload">
</form>
And in the function, I define policy and signature. However, I need to pass two variables to the form -- Content-Type and Key, which will only be known when the user presses the upload button. Thus, I need to pass these two variables to the template after the POST request but before the re-direction to Amazon.
It was suggested that I use urllib to do this. I have tried doing so the following way, but I keep getting an inscrutable HTTPError. This is what I currently have:
if request.method == 'POST':
# define the variables
urllib2.urlopen("https://me.amazonaws.com/",
urllib.urlencode([('key','videos/test3.jpg'),
('AWSAccessKeyId','<access_key'),
('acl','public-read'),
('policy',policy),
('signature',signature),
('Content-Type',content_type),
('file',file)]))
I have also tried hardcoding all the values instead of using variables but still get the same error. What am I doing incorrectly and what do I need to change to be able to redirect the form to Amazon, so the content can be uploaded directly to Amazon?
I recommend watching the form do its work with Firebug, enabled and set to the Net tab.
After completing the POST, click its [+] icon to expand, study the Headers, POST, Response tabs to see what you are missing and/or doing wrong.
Next separate this script from Django and put into a standalone file. Add one thing at a time to it and retest until it works. The lines below should increase visibility into your script.
import httplib
httplib.HTTPConnection.debuglevel = 1
I tried poking around with urllib myself, but as I don't have an account on AWS I didn't get farther than getting a 400 Bad Request response. Seems like a good sign, probably I just need valid host and key params etc.

Categories