Python CGI脚本:带两个提交按钮的基本HTML表单

6 投票
2 回答
11702 浏览
提问于 2025-04-16 22:13

我有一个简单的HTML表单,想要用两个提交按钮。这个CGI脚本会处理表单里的值(不管用哪个提交按钮),但是我希望每个按钮在脚本后面能执行不同的操作,也就是说,输出不同的结果:

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

任何建议都很感谢,谢谢。

2 个回答

0

CGI模块从Python 3.11开始就不再推荐使用了,并且在Python 3.13中会被完全移除。这是因为“每次请求都要启动一个新的Python实例”变得越来越不现实,甚至摩尔定律也跟不上代码的增长速度……

如果你将来想要使用“HTTP POST,并且提交按钮的选择很重要”的方式,这里有一种在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()
6
<input type="submit" value="Submit" name="Submit1" />
<input type="submit" value="Submit" name="Submit2" />

这样做可以让你在表单数据中得到不同的名字,具体取决于你按下了哪个提交按钮。

你可以这样做:

form = cgi.FieldStorage()

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

因为表单的行为就像一个Python中的字典,你可以检查某个名字是否在里面。它应该包含所有发送的表单元素的名字,所以,如果有一个输入框和两个提交按钮,它应该包含输入框的名字和被按下的提交按钮的名字

撰写回答