20.5 建立CGI应用程序
20.5.1 建立Web服务器
可以下载安装apache,网上有相关教程,不必赘述。
本书是在终端输入
python -m CGIHTTPServer
这将会在当前工作目录下,建立一个端口号为8000的Web服务器,然后可以在当前目录下创建一个cgi-bin文件夹,把CGI脚本都放入其中。把相关html文件放在当前工作目录下。(本节的所有例子都是如此)
20.5.2 建立表单页
<HTML><HEAD><TITLE>
Friends CGI Demo (static screen)
</TITLE></HEAD>
<BODY><H3>Friends list for: <I>NEW USER</I></H3>
<FORM ACTION="/cgi-bin/friends1.py">
<B>Enter your Name:</B>
<INPUT TYPE=text NAME=person VALUE="NEW USER" SIZE=15>
<P><B>How many friends do you have?</B>
<INPUT TYPE=radio NAME=howmany VALUE="0" CHECKED> 0
<INPUT TYPE=radio NAME=howmany VALUE="10"> 10
<INPUT TYPE=radio NAME=howmany VALUE="25"> 25
<INPUT TYPE=radio NAME=howmany VALUE="50"> 50
<INPUT TYPE=radio NAME=howmany VALUE="100"> 100
<P><INPUT TYPE=submit></FORM></BODY></HTML>
这个表单页面包括两个输入变量person和howmany,用户在输入这两个变量的值,并将表单提交后,这两个变量极其值会被CGI程序friends1.py读取。表单事件中缺少METHOD子标签,表示采用默认的GET方式提交请求。此外,ACTION='/cgi-bin/friends1.py'猜测是提交到相应的cgi应用程序,即'http://localhost:8000/cgi-bin/friends1.py'。
20.5.3 生成结果页
用户在按下submit后,表单就被提交到相应的CGI程序。
#-*-coding: utf-8-*-
# 所有请求采取默认的GET方法
import cgi
reshtml = '''Content-Type: text/html\n
<HTML><HEAD><TITLE>
Friends CGI Demo (dynamic screen)
</TITLE></HEAD>
<BODY><H3>Friends list for: <I>%s</I></H3>
Your name is <B>%s</B><P>
You have <B>%s</B> friends.
</BODY></HTML>'''
# 从这里开始读入并处理表单输入,同时向用户返回结果HTML文件
form = cgi.FieldStorage() # 表单变量是FieStorage实例化
who = form['person'].value
howmany = form['howmany'].value
print reshtml % (who, who, howmany)
结果如下:
20.5.4 生成表单和结果页面
这里只是将表单和结果页面放入程序里头,根据FieldStorage()实例化后,是否含有相应的键值对,来决定给客户端发送的是表单页面还是结果页面。
#-*-coding: utf-8-*-
import cgi
header = 'Content-Type: text/html\n\n' # HTTP MIME文件头,不知道这是什么
# 表单页面变量,包含三个变量action、person和howmany,其中action变量的值在表单页面中是'edit',action变量在这里的作用是作为一个表单页面的标识
formhtml = '''<HTML><HEAD><TITLE>
Friends CGI Demo</TITLE></HEAD>
<BODY><H3>Friends list for: <I>NEW USER</I></H3>
<FORM ACTION="/cgi-bin/friends2.py">
<B>Enter your Name:</B>
<INPUT TYPE=hidden NAME=action VALUE=edit>
<INPUT TYPE=text NAME=person VALUE="NEW USER" SIZE=15>
<P><B>How many friends do you have?</B>
%s
<P><INPUT TYPE=submit></FORM></BODY></HTML>'''
fradio = '<INPUT TYPE=radio NAME=howmany VALUE="%s" %s> %s\n' # 创建单选按钮的字符串变量,即friends.html文件中的9-13行的统一格式
# 对用户输入生成表单页面
def showForm():
friends = ''
for i in [0, 10, 25, 50, 100]:
checked = ''
if i == 0:
checked = 'CHECKED'
friends = friends + fradio % (str(i), checked, str(i)) # 即friends.html文件中的9-13行
print header + formhtml % (friends) # 将friends合并到formhtml中
# 结果页面变量,只有两个变量,person和howmany
reshtml = '''<HTML><HEAD><TITLE>
Friends CGI Demo</TITLE></HEAD>
<BODY><H3>Friends list for: <I>%s</I></H3>
Your name is <B>%s</B><P>
You have <B>%s</B> friends.
</BODY></HTML>'''
def doresult(who, howmany):
print header + reshtml % (who, who, howmany)
def process():
form = cgi.FieldStorage() # 读取有关的用户信息,在本例就是action、person和howmany这三个键值对
if form.has_key('person'):
who = form['person'].value
else:
who = 'NEW USER'
if form.has_key('howmany'):
howmany = form['howmany'].value
else:
howmany = 0
if form.has_key('action'):
doresult(who, howmany)
else: # 程序第一次运行时,并没有向cgi应用程序提交表单,所以form是不会有action这个键的
showForm()
if __name__ == "__main__":
process()
生成表单页面:
生成结果页面:
20.5.5 全面交互的Web站点
这一段代码与之前不同的是在结果页面加上链接,使用户可返回到表单页面,对所填信息进行编辑,另外也增加了错误页面,没有选择朋友数就提交,会直接转到错误页面,同样也可返回到表单页面。
#-*-coding: utf-8-*-
import cgi
from urllib import quote_plus
from string import capwords # 首字母大写,其余小写
header = 'Content-Type: text/html\n\n'
url = '/cgi-bin/friends3.py' # 单独抽出是因为表单页面和结果页面都会用到。
# 错误页面
errhtml = '''<HTML><HEAD><TITLE>
Friends CGI Demo</TITLE></HEAD>
<BODY><H3>ERROR</H3>
<B>%s</B><P>
<FORM><INPUT TYPE=button VALUE=back
ONCLICK="window.history.back()"></FORM>
</BODY></HTML>'''
def showError(error_str):
print header + errhtml % (error_str)
formhtml = '''<HTML><HEAD><TITLE>
Friends CGI Demo</TITLE></HEAD>
<BODY><H3>Friends list for: <I>%s</I></H3>
<FORM ACTION="%s">
<B>Your Name:</B>
<INPUT TYPE=hidden NAME=action VALUE=edit>
<INPUT TYPE=text NAME=person VALUE=%s SIZE=15>
<P><B>How many friends do you have?</B>
%s
<P><INPUT TYPE=submit></FORM></BODY></HTML>'''
fradio = '<INPUT TYPE=radio NAME=howmany VALUE="%s" %s> %s\n'
def showForm(who, howmany):
friends = ''
for i in [0, 10, 25, 50, 100]:
checked = ''
if str(i) == howmany: # 方便用户更新数据,所以这里的howmany依然是用户上次选定的数据,而非默认的0
checked = 'CHECKED'
friends = friends + fradio % (str(i), checked, str(i))
print header + formhtml % (who, url, who, friends)
reshtml = '''<HTML><HEAD><TITLE>
Friends CGI Demo</TITLE></HEAD>
<BODY><H3>Friends list for: <I>%s</I></H3>
Your name is <B>%s</B><P>
You have <B>%s</B> friends.
<P>Click <A HREF="%s">here</A> to edit your data again.
</BODY></HTML>'''
def doResults(who, howmany):
newurl = url + '?action=reedit&person=%s&howmany=%s' % (quote_plus(who), howmany) # 设置新的url是为了方便用户更新数据
print header + reshtml % (who, who, howmany, newurl)
def process():
error = ''
form = cgi.FieldStorage()
if form.has_key('person'):
who = capwords(form['person'].value)
else:
who = 'NEW USER'
if form.has_key('howmany'):
howmany = form['howmany'].value
else:
if form.has_key('action') and form['action'].value == 'edit': # 只输入person变量,而不选择howmany,就会连接到错误页面
error = 'Please select numbers of friends'
else:
howmany = 0
if not error:
if form.has_key('action') and form['action'].value != 'reedit':
doResults(who, howmany)
else:
showForm(who, howmany)
else:
showError(error)
if __name__ == "__main__":
process()
结果跟书上一样,就不贴了。