I am trying to use checkboxes to get the selected options from the user and pass it onto the views to create a new instance using the value, however, I am finding it difficult to get the input value as it keeps showing None the I try getting the value using the input name within the tag.
template
<form action='/print_from_button' method='GET'>
<table id="id_list_table" class="table table-condensed">
<thead>
<tr>
<th id="input">Input</th>
</tr>
</thead>
<tbody id="fbody">
{%for m in matches%}
<tr>
<td><br>{{ m.match }}</br> ({{m.datespent}})</td>
<td>
<input type="checkbox" name="inputs" class="checkvalue" value={{m.match}} />
</td>
</tr>
{%endfor%}
</tbody>
</table>
<input type="text" name="checkval" id="checkallvalues" size="50">
<button type='submit'> Confirm </button>
</form>
urls.py
from django.urls import path
from . import views
from .views import matchpaymentsoverview
from django.contrib.auth.decorators import login_required
urlpatterns = [
path('matchpayment/overview/',views.matchpaymentsoverview, name="matchpaymentsoverview"),
path('print_from_button', views.print_from_button)
]
views.py
def print_from_button(request):
print("button clicked")
if request.POST.get('checkval'):
vi = request.POST.get('checkval')
print(vi)
vi1 = request.GET.get('checkval')
print(vi1)
list_of_input_ids=request.POST.getlist('inputs')
print(list_of_input_ids)
return HttpResponse("""<html><script>window.location.replace('/');</script></html>""")
I keep getting none when I print the above name tags, would I need the button to trigger the function, or I can just create a function and use the get to get the values. Hope it makes sense.
Thanks
You could you HTML Checkboxes like this:
<p>Choose your monster's features:</p>
<div>
<input type="checkbox" id="scales" name="scales"
checked>
<label for="scales">Scales</label>
</div>
<div>
<input type="checkbox" id="horns" name="horns">
<label for="horns">Horns</label>
</div>
Basically this is just a input field with the type checkbox. You also could use Django input fields:
https://docs.djangoproject.com/en/3.2/ref/forms/
This is the source of my code:
https://developer.mozilla.org/de/docs/Web/HTML/Element/input/checkbox
Mozialla is a good choice in general if you have any questions about html, javascript or css
Related
I am trying to click on a radio button on a webpage which I am automating in Selenium Webdriver Python.
When my code tries to click on the radio button it is showing the error:
TypeError: 'WebElement' object is not callable:
The full error is:
Traceback (most recent call last):
File "C:\Webdriver\ClearCore\TestCases\MatchConfigrationPage_TestCase.py", line 85, in test_add_match_configuration_possibles_name
possibles_match_rules_tab.click_selected_rule_radio_button("Name")
File "C:\Webdriver\ClearCore\Pages\match_rules_tab.py", line 82, in click_selected_rule_radio_button
radio_button = self.driver.find_element(By.XPATH, '//table[#id="match_configuration_add_possible_tab_match_rules_ct_mapping_body"]//span[#title="Name" and contains(text(), "Name")]//ancestor::tr[1]//input[#type="radio"]')
TypeError: 'WebElement' object is not callable
I can find the button using the following XPATH in Firefox XPATH checker.
//table[#id="match_configuration_add_possible_tab_match_rules_ct_mapping_body"]//span[#title="Name" and contains(text(), "Name")]//ancestor::tr[1]//input[#type="radio"]
My method to call the button and click is as follows:
from selenium.webdriver.common.by import By
def click_selected_rule_radio_button(self, name):
# params name: The name of the data object to be selected for the match rule, e.g. Name, Address
radio_button = self.driver.find_element(By.XPATH, '//table[#id="match_configuration_add_possible_tab_match_rules_ct_mapping_body"]//span[#title="%s" and contains(text(), "%s")]//ancestor::tr[1]//input[#type="radio"]' (name, name))
self.driver.execute_script("arguments[0].click()", radio_button)
return self
the name parameter in the method it's value is "Name", %s in the code has the value "Name"
I have also tried the following:
def click_selected_rule_radio_button2(self, name):
# params name: The name of the data object to be selected for the match rule, e.g. Name, Address
#WebDriverWait(self.driver, 20).until(EC.presence_of_all_elements_located((By.ID, 'match_configuration_add_possible_tab_match_rules_ct_mapping_body')))
radio_button = WebDriverWait(self.driver, 20).until(EC.presence_of_element_located((By.XPATH, '//table[#id="match_configuration_add_possible_tab_match_rules_ct_mapping_body"]//span[#title="Name" and contains(text(), "Name")]//ancestor::tr[1]//input[#type="radio"]')))
radio_button.click()
return self
From my TestCase class i call the method as follows:
possibles_match_rules_tab.click_selected_rule_radio_button("Name")
code snippet of test case is as follows:
def test_add_match_configuration_possibles_name(self):
print "*** Test add Match Configuration Possibles - Name ***"
projectNavigator = project_navigator.ProjectNavigatorPage(self.driver)
possiblesPage = projectNavigator.select_projectNavigator_item("Possibles") # click Possibles from project navigator
possiblesPage.click_add_possibles_button()
possiblesPage.enter_possible_matches_name_and_description_from_details_tab("name_dob", "date of birth possible match rule")
possibles_match_rules_tab = possiblesPage.click_match_rules_tab()
possibles_match_rules_tab.click_possibles_match_rules_add_button()
possibles_match_rules_tab.enter_match_rule_name("name_dob")
possibles_match_rules_tab.click_selected_rule_radio_button("Name")
The HTML is:
<table id="match_configuration_add_possible_tab_match_rules_ct_mapping_body" cellspacing="0" style="table-layout: fixed; width: 100%;">
<colgroup>
<tbody>
<tr class="GPI5XK1CFG" __gwt_subrow="0" __gwt_row="0">
<td class="GPI5XK1CEG GPI5XK1CGG GPI5XK1CHG">
<div __gwt_cell="cell-gwt-uid-339" style="outline-style:none;" tabindex="0">
<input type="radio" name="rbCrossRow2" />
</div>
</td>
<td class="GPI5XK1CEG GPI5XK1CGG">
<div __gwt_cell="cell-gwt-uid-340" style="outline-style:none;">
<span class="" title="Name" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;padding-right: 1px;">Name</span>
</div>
</td>
<td class="GPI5XK1CEG GPI5XK1CGG GPI5XK1CBH">
<div __gwt_cell="cell-gwt-uid-341" style="outline-style:none;">
<input id="match_configuration_add_possible_tab_match_rules_cb_name" type="checkbox" />
</div>
</td>
</tr>
<tr class="GPI5XK1CEH" __gwt_subrow="0" __gwt_row="1">
<td class="GPI5XK1CEG GPI5XK1CFH GPI5XK1CHG">
<div __gwt_cell="cell-gwt-uid-339" style="outline-style:none;">
<input type="radio" name="rbCrossRow2" />
</div>
</td>
<td class="GPI5XK1CEG GPI5XK1CFH">
<div __gwt_cell="cell-gwt-uid-340" style="outline-style:none;">
<span class="" title="Address" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;padding-right: 1px;">Address</span>
</div>
</td>
<td class="GPI5XK1CEG GPI5XK1CFH GPI5XK1CBH">
</tr>
<tr class="GPI5XK1CFG" __gwt_subrow="0" __gwt_row="2">
<tr class="GPI5XK1CEH" __gwt_subrow="0" __gwt_row="3">
</tbody>
Can anyone see what is wrong, why the radio button is not callable, it will not click it?
Thanks,
Riaz
You can use JavaScript to click radio button.Code is as follow:
driver=webdriver.Chrome('./chromedriver.exe')
driver.get('your URL')
time.sleep(10)
radioButton = driver.find_element_by_xpath("Radio Button Xpath") #like //input[#id='female']
driver.execute_script("arguments[0].click();", radioButton)
#driver.quit()
I have the following HTML structure. A table with rows, the 2nd column has the text displayed e.g. Title (in row 1), FName (in row 2), SNAME (in row3), GENDER etc.
The 3rd column has a checkbox for each row.
I am trying to select a particular checkbox. E.g. my method will accept a parameter (the name of the text value in the row e.g. TITLE).
The method will select the checkbox for TITLE.
When i call the method again with parameter FNAME, the checkbox for FNAME will be clicked.
I am using Selenium Webdriver with Python
I have tried the following XPATH to identify the checkbox:
//span[#title="TITLE" and contains(text(), "TITLE")]/following-sibling::*
//span [text()="TITLE"]/../../preceding-sibling::td/div/input[#type="checkbox"]
These do not find the checkbox for the row called TITLE
I can get to the TITLE with the following XPATH.
//span [text()="TITLE"]
My code snippet is:
def add_mapping2(self, name):
try:
checkbox = self.driver.find_element(By.XPATH, '//span [text()="+name+"]/../../preceding-sibling::td/div/input[#type="checkbox"]')
checkbox.click()
except NoSuchElementException, e:
return False
return True
From my unittest.Testcase class I call the method as follows:
class MappingsPage_TestCase(BaseTestCase):
def test_add_mappings(self):
mappingsPage = projectNavigator.select_projectNavigator_item("Mappings")
mappingsPage.add_mapping2("TITLE")
mappingsPage.add_mapping2("SNAME")
The HTML is:
<table id="data_configuration_edit_mapping_tab_mappings_ct_mapping_body" cellspacing="0" style="table-layout: fixed; width: 100%;">
<colgroup>
<tbody>
<tr class="GOFU2OVFG" __gwt_subrow="0" __gwt_row="0">
<tr class="GOFU2OVEH GOFU2OVGH GOFU2OVPG GOFU2OVMG" __gwt_subrow="0" __gwt_row="1">
<td class="GOFU2OVEG GOFU2OVFH GOFU2OVHG GOFU2OVHH GOFU2OVAH GOFU2OVNG">
<td class="GOFU2OVEG GOFU2OVFH GOFU2OVHH GOFU2OVAH GOFU2OVNG">
<div __gwt_cell="cell-gwt-uid-792" style="outline-style:none;">
<span title="TITLE" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;padding-right: 1px;">TITLE</span>
</div>
</td>
<td class="GOFU2OVEG GOFU2OVFH GOFU2OVHH GOFU2OVBH GOFU2OVOG GOFU2OVAH GOFU2OVNG">
<div __gwt_cell="cell-gwt-uid-793" style="outline-style:none;" tabindex="0">
<input type="checkbox" checked="" tabindex="-1"/>
</div>
</td>
</tr>
<tr class="GOFU2OVFG" __gwt_subrow="0" __gwt_row="2">
<td class="GOFU2OVEG GOFU2OVGG GOFU2OVHG">
<div __gwt_cell="cell-gwt-uid-791" style="outline-style:none;">
<input type="radio" name="rbCrossRow124"/>
</div>
</td>
<td class="GOFU2OVEG GOFU2OVGG">
<div __gwt_cell="cell-gwt-uid-792" style="outline-style:none;">
<span class="" title="FNAME" style="white-space:nowrap;overflow:hidden;text-overflow:ellipsis;empty-cells:show;display:block;padding-right: 1px;">FNAME</span>
</div>
</td>
<td class="GOFU2OVEG GOFU2OVGG GOFU2OVBH">
<div __gwt_cell="cell-gwt-uid-793" style="outline-style:none;">
<input type="checkbox" tabindex="-1"/>
</div>
</td>
</tr>
<tr class="GOFU2OVEH" __gwt_subrow="0" __gwt_row="3">
<tr class="GOFU2OVFG" __gwt_subrow="0" __gwt_row="4">
<tr class="GOFU2OVEH" __gwt_subrow="0" __gwt_row="5">
<tr class="GOFU2OVFG" __gwt_subrow="0" __gwt_row="6">
more rows with names with checkboxes etc......
</tbody>
</table>
What XPATH could I use to get the checkbox for TITLE, FNAME etc?
I have the table ID "data_configuration_edit_mapping_tab_mappings_ct_mapping_body"
Maybe there is a way to start from the table ID and use a for loop to iterate through the rows and find the particular checkbox?
Thanks.
Riaz
you would use the following xpath expression
String xpath = "//span[#title = 'TITLE']/ancestor::tr[1]//input[#type = 'checkbox']"
What it does:
first search for a span element with your parameter (pls change 'TITLE' to the variable you are using)
then find the first ancestor element that is a tr-element
from there find the input element that is your checkbox within this tr-element
You could then refine to sth like this:
WebElement table = driver.findElement(By.id("data_configuration_edit_mapping_tab_mappings_ct_mapping_body"));
WebElement checkbox = table.findElement(By.xpath(xpath));
For the interest of others whom come across a similar problem. My Python code which I have used for the above answer is:
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
def add_mapping(self, name):
wait = WebDriverWait(self.driver, 10)
try:
checkbox = wait.until(EC.element_to_be_clickable((By.XPATH, '//span[#title = "%s"]/ancestor::tr[1]//input[#type = "checkbox"]' % name)))
#table_id = self.driver.find_element(wait.until(EC.element_to_be_clickable(By.ID, 'data_configuration_edit_mapping_tab_mappings_ct_mapping_body')))
#checkbox = table_id.find_element(By.XPATH, '//span[#title = "TITLE"]/ancestor::tr[1]//input[#type = "checkbox"]')
checkbox.click()
except NoSuchElementException, e:
return False
return True
The table id i commented out also works.
I have the following code :
{% for assessments in list_assessments%}
<form action="/test/" method="post">{%csrf_token%}
<tr>
<td>{{assessments.assessment_id}}</td>
<td>{{assessments.name}}</td>
<td>{{assessments.assessment_begin_date}}</td>
<td>{{assessments.assessment_end_date}}</td>
<td>{{assessments.is_active}}</td>
<td>{{assessments.is_complete}}</td>
<td>{{assessments.created_at}}</td>
<td>{{assessments.updated_at}}<br></td>
<td><input type="submit" value="Edit Assessment" /></td>
</tr>
{%endfor%}
</form>
All the data here are dynamically coming.
In this following code, i need to assign an name to assessments.name dynamically, something like
<td name="dynamic_name">{{assessment.name}}</td>.
And on clicking the button "Edit Assessment", i want the dynamic_name to be passed and received my the view.
The idea is each assessment has its own set of parameters. I want to display only the parameters related to the name. So if i could pass the value i would be able to do it.
Any help appreciated.
Your ending **</form>** tag should be before for loop.
{% for assessments in list_assessments%}
<form action="/test/" method="post" name="form-{{ assessments.counter }}">{%csrf_token%}
<tr>
<td>{{assessments.assessment_id}}</td>
<td>{{assessments.name}}</td>
<td>{{assessments.assessment_begin_date}}</td>
<td>{{assessments.assessment_end_date}}</td>
<td>{{assessments.is_active}}</td>
<td>{{assessments.is_complete}}</td>
<td>{{assessments.created_at}}</td>
<td>{{assessments.updated_at}}<br></td>
<td><input type="submit" value="Edit Assessment" /></td>
</tr>
</form>
{%endfor%}
Now, You can get specific block values by form name ( see above code ) in javascript as well as in python.
In Javascript,
form = document.getElementByTagName("form")
elems = form.children("td")
elems will give you all td elements.
So I'm using jQuery UI to skin the radio buttons but I can't get Django to render my form the way it has to be done.
I need to have this structure:
<table>
<tr>
<td><label for="notify_new_friends">Notify when new friends join</label></td>
<td class="radio">
<input type="radio" name="notify_new_friends" id="notify_new_friends_immediately" value="1" checked="checked"/><label for="notify_new_friends_immediately">Immediately</label>
<input type="radio" name="notify_new_friends" id="notify_new_friends_never" value="0"/><label for="notify_new_friends_never">Never</label>
</td>
</tr>
</table>
So to summarize that I need the radio buttons within a class (radio) where they have an input and a label for.
When I render the form in my template with {{ profile_form.notify_new_friends }} I get the following:
<ul>
<li><label for="id_notify_new_friends_0"><input type="radio" id="id_notify_new_friends_0" value="0" name="notify_new_friends" /> Immediately</label></li>
<li><label for="id_notify_new_friends_1"><input type="radio" id="id_notify_new_friends_1" value="1" name="notify_new_friends" /> Never</label></li>
</ul>
Which is exactly what I want except for the list-part. So I tried looping over it which gives me the labels formatted differently:
{% for item in profile_form.notify_new_friends %}
{{ item }}
{% endfor %}
which gives me:
<label><input type="radio" name="notify_new_friends" value="0" /> Immediately</label>
<label><input type="radio" name="notify_new_friends" value="1" /> Never</label>
So the problem here is that it stops using label for and starts using just label to wrapp it all with.
I also tried doing something like this, but then the label and label_tag don't render anything.
{{ profile_form.notify_new_friends.0 }}
{{ profile_form.notify_new_friends.0.label_tag }}
{{ profile_form.notify_new_friends.0.label }}
So does anyone know how I can render this properly!?
FYI, this is my forms.py:
self.fields['notify_new_friends'] = forms.ChoiceField(label='Notify when new friends join', widget=forms.RadioSelect, choices=NOTIFICATION_CHOICES)
In my code I discovered that changing the widget from
forms.RadioSelect
to
forms.RadioSelect(attrs={'id': 'value'})
magically causes the resulting tag value to include the id attribute with the index of the item appended. If you use
{% for radio in form.foo %}
<li>
{{ radio }}
</li>
{% endfor %}
in the form you get a label wrapped around an input. If you want the more conventional input followed by label, you need to do this:
{% for radio in form.value %}
<li>
{{ radio.tag }}
<label for="value_{{ forloop.counter0 }}">{{ radio.choice_label }}</label>
</li>
{% endfor %}
Unfortunately this is more complicated than it should be, it seems you need to override at least 2 classes: RadioRenderer and RadioInput. The following should help you get started but you might need to tweak it a little.
First create a custom radio button input widget. The only purpose of us overriding the render method is to get rid of annoying structure Django enforces (<label><input /></label>) where instead we want ours (<label /><input />):
class CustomRadioInput(RadioInput):
def render(self, name=None, value=None, attrs=None, choices=()):
name = name or self.name
value = value or self.value
attrs = attrs or self.attrs
if 'id' in self.attrs:
label_for = ' for="%s_%s"' % (self.attrs['id'], self.index)
else:
label_for = ''
choice_label = conditional_escape(force_unicode(self.choice_label))
return mark_safe(u'%s<label%s>%s</label>' % (self.tag(), label_for, choice_label))
Now we need to override RadioRenderer in order to:
Force it to use our custom radio input widget
Remove <li> wraping every single input field and <ul> wrapping all input fields:
Something along these lines should do:
class RadioCustomRenderer(RadioFieldRenderer):
def __iter__(self):
for i, choice in enumerate(self.choices):
yield CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, i)
def __getitem__(self, idx):
choice = self.choices[idx]
return CustomRadioInput(self.name, self.value, self.attrs.copy(), choice, idx)
def render(self):
return mark_safe(u'%s' % u'\n'.join([u'%s' % force_unicode(w) for w in self]))
Finally instruct Django to use custom renderer
notify_new_friends = forms.ChoiceField(label='Notify when new friends join', widget=forms.RadioSelect(renderer=RadioCustomRenderer), choices=NOTIFICATION_CHOICES)
Please bear in mind: This now outputs radio buttons together with encompassing <td> hence you need to build a table around it in your template, something along these lines:
<table>
<tr>
<td><label for="{{field.auto_id}}">{{field.label}}</label></td>
<td>{{ field.errors }} {{field}}</td>
</tr>
</table>
If anyone stumble upon this problem and just want to render the radio button without ul: they should follow this link.
https://docs.djangoproject.com/en/3.1/ref/forms/widgets/#selector-widgets
Example below.
{% for radio in myform.beatles %}
<div class="myradio">
{{ radio }}
</div>
{% endfor %}
Since it doesn't seem to be a good way to do this I chose to rearrange the generated code using jQuery.
// First remove the ul and li tags
$('.radio ul').contents().unwrap();
$('.radio li').contents().unwrap();
// Then move the input to outside of the label
$('.radio > label > input').each(function() {
$(this).parent().before(this);
});
// Then apply the jQuery UI buttonset
$( ".radio" ).buttonset();
This made it go from:
<ul>
<li><label for="id_notify_new_friends_0"><input type="radio" id="id_notify_new_friends_0" value="0" name="notify_new_friends" /> Immediately</label></li>
<li><label for="id_notify_new_friends_1"><input type="radio" id="id_notify_new_friends_1" value="1" name="notify_new_friends" /> Never</label></li>
</ul>
to:
<input type="radio" id="id_notify_new_friends_0" value="0" name="notify_new_friends" /><label for="id_notify_new_friends_0"> Immediately</label></li>
<input type="radio" id="id_notify_new_friends_1" value="1" name="notify_new_friends" /><label for="id_notify_new_friends_1"> Never</label></li>
and my jQuery UI styling works fine.
Try like this , I got it..
from django.forms.widgets import RadioFieldRenderer
from django.utils.encoding import force_unicode
from django.utils.safestring import mark_safe
class RadioCustomRenderer( RadioFieldRenderer ):
def render( self ):
return mark_safe(u'%s' % u'\n'.join([u'%s' % force_unicode(w) for w in self]))
in form
widgets = {
'validity': forms.RadioSelect(renderer=RadioCustomRenderer),
}
Using django, I have a form in which a user enters his 'position'. The user may add multiple positions. The user may also delete positions. There are two things worth noting with this:
1) in the form, there are two buttons, 'Add' and 'Delete'.
2) I am using a for loop in the template to populate the list of positions and delete buttons.
This is what I currently have:
# in template
<tr>
<td>Position</td>
<td>{{ form.position }}
<input type="submit" value="Add" , name='action'/>
</td>
</tr>
<tr>
<td> </td>
<td>
{% for position in positions %}
{{ position}}
<input type="submit" value="Delete {{position }}", name='action'/>
{% endfor %}
</td>
</tr>
# in views.py
...
if action == 'Add':
positions.append(request.POST['position'])
return render_to_response(...)
if 'Delete' in action:
positions.remove(request.POST['action'][7:])
return render_to_response('...)
This seems like a very inelegant way to do the "Deletion" part.
Is there a better way to get the value of the position, without having to cram in additional information in the 'Delete' submit button, and then slicing it off to get its value?
I see three options here:
Use checkbox field for each position and one "Delete" button. In that case a user can choose multiple positions to be deleted and you can get their IDs from request easily.
Use a hidden field position and a little bit of Javascript to fill it. If you use jquery it could be:
<input type="hidden" name="position" value="" />
{% for position in positions %}
<input type="submit" value="Delete" name="action" data-position="{{ position }}" />;
{% endfor %}
<script type="text/javascript">
var $position_input = $("input[name='position']");
$("input[name='action'][value='Delete'].click(function(e) {
var $this = $(this);
var position = $this.data("position");
$position_input.val(position);
});
</script>
Insert position ID into name attribute, like this:
<input type="submit" value="Delete" name="delete-position.{{ position }} />
In view function you'll have to look through all data in request.POST and find all items which start with delete-position and then use slicing.