6

I have a basic html form which I want to use with two submit buttons. The CGI script takes the form value and processes it (regardless of which submit button used), but I want each button to be associated with different actions later in the script, i.e. print different output:

##  Get the form value in the usual way.
form = cgi.FieldStorage()
RawSearchTerm = form.getvalue("QUERY")

##  Process the form info etc.

if (button1 was pressed):
    print this
elif (button2 was pressed):
    print this other thing

Any ideas appreciated, thanks.

2 Answers 2

6
<input type="submit" value="Submit" name="Submit1" />
<input type="submit" value="Submit" name="Submit2" />

This will give you a different name in your form data depending on which submit button was pressed.

You can do

form = cgi.FieldStorage()

if "Submit1" in form:
    button = 1
elif "Submit2" in form:
    button = 2
else:
    print "Couldn't determine which button was pressed."

because form acts like a Python dict and you can check if a given name is in it. It should include the names of all form entities sent, so, with one field and two submit buttons, it should contain the name of the form field and the name of the submit button that was pressed.

Sign up to request clarification or add additional context in comments.

6 Comments

I'm sorry, I don't understand fully. The form I am using has only one field; is the name of the submit button used to submit the form stored with the variable that is submitted? If I print the variable 'RawSearchTerm' it just prints the data entered by the user. How do I find out in the CGI script which button was used?
The submit button that is pressed should add another field if it has a name attribute set.
Look at my answer, I edited it before I posted that comment. You can either do if "fieldName" in form: to be safe, or form["fieldName"] if you know fieldName is there and you want the fields value rather than its name.
It turns out, this solution is only possible if the type="submit" shows up AFTER the name and value portion. The examples shown in this answer don't work, but this does: `<input value="Submit" name="Submit1" type="submit">'
@ChrisNielsen Are you sure? This worked for me when posted, and also for the person who asked the question.
|
0

The CGI module is deprecated starting in Python 3.11 and will be removed in Python 3.13 (since "spinning up a new Python instance for every single request" is getting less feasible as time goes on; even Moore's law can't keep up with the code swell...)

If you want to take the "HTTP POST where the choice of submit button matters" route in the future, here's how you might do it in WSGI:

<!-- client side (no JS required!) -->
<form action="/cgi-bin/do.py" method="POST">
<input name="username" placeholder="username" required/>
<button type="submit" value="login" name="submitter">Log In</button>
<button type="submit" value="register" name="submitter">Register New User</button>
<button type="submit" value="reset" name="submitter">Reset Password</button>
</form>
# server side (no pypi packages required!)
# eschews cgi library, for Python 3.11+
import urllib.parse

def main_wsgi(environ, start_response):
    if environ['PATH_INFO'] == '/cgi-bin/do.py':
        assert environ['REQUEST_METHOD'] == 'POST'
        
        form = _parse_form(environ)
        action = form.get('submitter')
        username = form.get('username')
        assert '<' not in username
        
        start_response('200 OK', [('Content-Type', 'text/html')])
        yield '<h1>'.encode()
        match action:
            case 'login':
                yield f'Logged in as {username}!'.encode()
            case 'register':
                yield f'"{username}" registered!'.encode()
            case 'reset':
                yield f'Password reset. Check your e-mail, {username}!'.encode()
            case _:
                yield f'400 Nice Try'.encode()
        yield '</h1>'.encode()
        
    else:
        assert environ['REQUEST_METHOD'] == 'GET'
        start_response('200 OK', [('Content-Type', 'text/html')])
        yield '<form action="/cgi-bin/do.py" method="POST">'.encode()
        yield '<input name="username" placeholder="username" required />'.encode()
        yield '<button type="submit" value="login" name="submitter">Log In</button>'.encode()
        yield '<button type="submit" value="register" name="submitter">Register New User</button>'.encode()
        yield '<button type="submit" value="reset" name="submitter">Reset Password</button>'.encode()
        yield '</form>'.encode()

def _parse_form(environ, /):
    assert environ['CONTENT_TYPE'] == 'application/x-www-form-urlencoded', 'NotImplementedError; TODO\nhttps://andrew-d.github.io/python-multipart'
    l = int(environ['CONTENT_LENGTH'])
    body = environ['wsgi.input'].read(l)
    body = body.decode('ascii', errors='surrogateescape')
    return dict(urllib.parse.parse_qsl(body))

if __name__ == '__main__':
    import wsgiref.simple_server
    wsgiref.simple_server.make_server('', 8000, main_wsgi).serve_forever()

1 Comment

It's worth noting that this example doesn't handle multipart/form-data, which is needed to handle file uploads. I've got a more fleshed-out example here.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.