Lets say I have this kind of html
<form method post="some.page">
.
.
<span class="warning"
<img class"something_img" src="some.jpg" title="jpg title">
</span>
.
.
<p class="input">
<input class="input" type="submit" value="Click Here" name="action">
</p>
.
.
</form>
<form method post="some.page">
.
.
<p class="input">
<input class="input" type="submit" value="Click Here" name="action">
</p>
.
.
</form>
The jest is, the page is made out of lots of forms, but I need to locate only submit buttons in forms where the class "warning" exist and skip the inputs where it doesn't.. there can be a lot! of this forms some of them have the "warning" class and some of them don't and I need to click on the first that does have it... (script will than do it stuff, and come back when done to the main page where it again have to look for the input of form where the warning is...it will be on next form as script will solve the issue with old warning )
I'm not sure how to locate that reliably with selenium and python.
I would first filter out all the forms that don't have an element with the 'warning' class, and then get the submit button(s) in the valid forms via their XPaths:
# find all forms
forms = driver.find_elements_by_tag_name("form")
# create list of forms that only contain elements with 'warning' class
forms_with_warnings = [form for form in forms if len(form.find_elements_by_class_name("warning")) > 0]
# create list of buttons and fill it with found inputs in valid forms
buttons = []
for form in forms_with_warnings:
buttons.extend(form.find_elements_by_xpath('//input[type="submit"]'))
I hope something like this helps! You could also do the filtering via the filter function instead of a list comprehension; whatever you're more comfortable with.
Related
I am building an app using Flask to show nearby shops, and the user can like a shop so it can be added to their liked shops list.
My question is how can i get the value inside the <h4> tag sent to Python knowing that the name attribute is a variable. The html code is below:
<form name='likeF' method='POST' action ='{{url_for("liked")}}'>
<h4 name="ShopName_{{loop.index}}">{{item.ShopName}}</h4>
<p>
Shop Description : {{item.ShopDesc}} <br>
<button type="submit" class="success button like">Like</button>
distance: {{item.ShopDistance}}
</p>
</form>
So please how am I supposed to get back the value of {{item.ShopName}}?
You can't send the text inside an <h4> tag (or any tag that is not a form input) back to the server, at least not without using Javascript. The easiest method would be to duplicate it in a hidden input element inside the form, such as:
<input type="hidden" name="ShopName" value="{{ item.ShopName }}">
Then you can access it using request.form["ShopName"].
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!
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);
}
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()
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.