Python mechanize - two buttons of type 'submit'

前端 未结 4 1460
刺人心
刺人心 2021-02-02 09:42

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 fo

相关标签:
4条回答
  • 2021-02-02 10:04

    Use the 'click' method. E.g.

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

    Should work.

    0 讨论(0)
  • 2021-02-02 10:16

    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>.

    0 讨论(0)
  • 2021-02-02 10:19

    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.

    0 讨论(0)
  • 2021-02-02 10:20

    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.

    0 讨论(0)
提交回复
热议问题