views:

2529

answers:

5

I have a mechanize script written in python that fills out a web form and is supposed to click on the 'create' button. But there's a problem, the form has two buttons. One for 'add attached file' and one for 'create'. Both are of type 'submit', and the attach button is the first one listed. So when I select the forum and do br.submit(), it clicks on the 'attach' button instead of 'create'. Extensive Googling has yielded nothing useful for selecting a specific button in a form. Does anyone know of any methods for skipping over the first 'submit' button and clicking the second?

+2  A: 

I can talk from experience using HTTP, rather than mechanize, but I think this is probably what you want.

When there are two submit buttons in a form, a server can determine which one was pressed, because the client should have added an argument for the submit button. So:

<form action="blah" method="get">
    <p>
        <input type="submit" name="button_1" value="One" />
        <input type="submit" name="button_2" value="Two" />
    </p>
</form>

Will take you either the URL:

blah?button_1=One

or:

blah?button_2=Two

Depending on which button was pressed.

If you're programatically determining what arguments are going to be sent, you need to add an argument with the name of the submit button that was pressed, and it's value.

SpoonMeiser
+1  A: 

I would suggest you to use Twill which uses mechanize (mostly monkeypatched). So say you have form with some fields and two submit buttons with names "submit_to_preview" and "real_submit". Following code should work.

BTW remember this is not threadsafe so you might want to use locks in case if you want to use the code in a threaded env.

import twill.commands
b = twill.get_browser()
url = "http://site/myform"
twill.commands.go(url)
twill.commands.fv("2", "name", "Me")
twill.commands.fv("2", "age", "32")
twill.commands.fv("2", "comment", "useful article")
twill.commands.browser.submit("real_submit")

Hope that helps. Cheers.

Shekhar
A: 

is there any module suport js browser ? mechanize does not support js

spiderMonkey, although I heard that it was very complex
BlueTrin
+2  A: 

Use the 'click' method. E.g.

mybrowser.select_form(nr=0)
req = mybrowser.click(type="submit", nr=1)
mybrowser.open(req)

Should work.

Kyle
A: 

I tried using the nr parameter, without any luck.

I was able to get it to work with a combination of the name and label parameters, where "label" seems to correspond to the "value" in the HTML:

Here are my two submit buttons:

<input type="submit" name="Preview" value="Preview" />
<input type="submit" name="Create" value="Create New Page" />

... and here's the code that clicks the first one, goes back, and then clicks the second:

from mechanize import Browser
self.br = Browser()
self.br.open('http://foo.com/path/to/page.html')
self.br.select_form(name='my_form')
self.br['somefieldname'] = 'Foo'
submit_response = self.br.submit(name='Preview', label='Preview')
self.br.back()
self.br.select_form(name='my_form')
self.br['somefieldname'] = 'Bar'
submit_response = self.br.submit(name='Create', label='Create New Page')

There's a variant that also worked for me, where the "name" of the submit button is the same, such as:

<input type="submit" name="action" value="Preview" />
<input type="submit" name="action" value="Save" />
<input type="submit" name="action" value="Cancel" />

and

self.br.select_form(name='my_form')
submit_response = self.br.submit(name='action', label='Preview')
self.br.back()
submit_response = self.br.submit(name='action', label='Save')

IMPORTANT NOTE - I was only able to get any of this multiple-submit-button code to work after cleaning up some HTML in the rest of the page.

Specifically, I could not have <br/> - instead I had to have <br /> ... and, making even less sense, I could not have anything between the two submit buttons.

It frustrated me to no end that the mechanize/ClientForm bug I hunted for over two hours boiled down to this:

<tr><td colspan="2"><br/><input type="submit" name="Preview" value="Preview" />&nbsp;<input type="submit" name="Create" value="Create New Page" /></td></tr>

(all on one line) did not work, but

<tr><td colspan="2"><br />
<input type="submit" name="Preview" value="Preview" />
<input type="submit" name="Create" value="Create New Page" /></td></tr>

worked fine (on multiple lines, which also shouldn't have mattered).

I like mechanize because it was easy to install (just copy the files into my include directory) and because it's pretty simple to use, but unless I'm missing something major, I think that bugs like this are kind of awful - I can't think of a good reason at all why the first example there should fail and the second should work.

And, incidentally, I also found another mechanize bug where a <textarea> which is contained within a <p> is not recognized as a valid control, but once you take it out of the <p> container it's recognized just fine. And I checked, textarea is allowed to be included in other block-level elements like <p>.

Chirael