首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

19.5  处理输入

多数想建立动态网站的人都会想和用户交互。有两种取得用户输入的方法:通过表单(或类似表单的东西)字段和URL的附加部分。如果您已经学习了第18章(关于CGI),您就会清楚CGI也提供同样的选择(如果您对客户端感兴趣,第6章介绍了从客户端提交数据)。为了帮您理解在mod_python中输入是如何工作的,我修改了第18章中的CGI例子。如果您想从CGI和mod_python中选择一个,那么通过对比这两个例子,就可以看出这两种技术的区别。

19.5.1  附加的URL部分

在CGI中,您可以在URL的Python处理程序名后面加上任何您喜欢的部分。附加的部分在对象中保存为req.path_info,并传递给handler()函数。下面是把这个CGI例子中的函数改写为标准mod_python的程序。这个例子会询问您今天的日期,代码如下:

# mod_python path_info example -- Chapter 19 -- pathinfo.py

from mod_python import apache

import time

monthmap = {1: 'January', 2: 'February', 3: 'March', 4: 'April', 5:   'May',

    6: 'June', 7: 'July', 8: 'August', 9: 'September', 10: 'October',

    11: 'November', 12: 'December'}

daymap = {0: 'Monday', 1: 'Tuesday', 2: 'Wednesday', 3: 'Thursday',

    4: 'Friday', 5: 'Saturday', 6: 'Sunday'}

def getscriptname(req):

    if not len(req.path_info):

        return req.uri

    return req.uri[:-len(req.path_info)]

def month_quiz(req):

    req.write("What month is it?<P>\n")

    for code, name in monthmap.items():

        req.write('<A HREF="%s/%d">%s</A><BR>' % (getscriptname(req),

                   code, name))

def day_quiz(req):

    month = time.localtime()[1]

    req.write("What day is it?<P>\n")

    for code, name in daymap.items():

        req.write('<A HREF="%s/%d/%d">%s</A><BR>' % (getscriptname(req),

                  month, code, name))

def check_month_answer(req, answer):

    month = time.localtime()[1]

    if int(answer) == month:

        req.write("Yes, this is <B>%s</B>.<P>\n" % monthmap[month])

        return 1

    else:

        req.write("Sorry, you're wrong. Try again:<P>\n")

        month_quiz(req)

        return 0

def check_day_answer(req, answer):

    day = time.localtime()[6]

    if int(answer) == day:

        req.write("Yes, this is <B>%s</B>.\n" % daymap[day])

        return 1

    else:

        req.write("Sorry, you're wrong. Try again:<P>\n")

        day_quiz(req)

        return 0

def handler(req):

    req.content_type = "text/html"

    if req.header_only:

        return apache.OK

    req.write("""<HTML>

<HEAD>

<TITLE>mod_python PATH_INFO Example</TITLE></HEAD><BODY>""")

    input = req.path_info.split('/')[1:]

    if not len(input):

        month_quiz(req)

    elif len(input) == 1:

        ismonthright = check_month_answer(req, input[0])

        if ismonthright:

            day_quiz(req)

    else:

        ismonthright = check_month_answer(req, input[0])

        if ismonthright:

            check_day_answer(req, input[1])

       

    req.write("\n</BODY></HTML>\n")

    return apache.OK

让我们来看一下这个程序,您会看到它和第18章中的pathinfo.cgi非常类似。事实上,这里唯一的改动是从req中取得数据,而不是环境变量,而且使用req.write()把数据传回客户端。

程序会在URL的脚本名后面添加信息。这些新的数据会被Apache传入req.path_info,而且可以被程序使用。通过这些新的数据,程序可以确定用户的输入并产生适当的应答。

如果您用过本章前面介绍的Apache配置文件的例子,您就可以通过http://localhost/py/ pathinfo.prog这个地址来运行该例子。首先,您将被问到当前是几月。当您回答正确后,您将被问今天是星期几。在您正确回答这两个例子后,您会看到一条确认您选择的信息。

为什么不是CGI处理程序

mod_python的发行版本中包含一个CGI处理程序,它设计成仿效传统的Python CGI环境。然而,由于Apache mod_python环境和CGI环境还是有很大不同的,所以这个仿效还有些缺点,而且事实上,最主要的是它失去了使用mod_python的好处。因此mod_python的作者和我都不建议使用mod_python中的CGI处理程序,如果您将要使用mod_python,那么最好更新代码使用纯mod_python,不要使用其中的CGI处理程序。

19.5.2  GET方法

不用添加一个虚拟文件路径,GET方法可以用来把数据传递给程序。GET方法会在URL后面编码参数。您可以手工构造URL,或是使用HTML表单来让浏览器根据输入为您构造。下面

是用GET方法改写前面例子的程序。和前面的例子一样,这个例子会根据今天的日期产生一个问题:

# mod_python GET example -- Chapter 19 -- get.py

from mod_python import apache, util

import time

monthmap = {1: 'January', 2: 'February', 3: 'March', 4: 'April', 5: 'May',

    6: 'June', 7: 'July', 8: 'August', 9: 'September', 10: 'October',

    11: 'November', 12: 'December'}

daymap = {0: 'Monday', 1: 'Tuesday', 2: 'Wednesday', 3: 'Thursday',

    4: 'Friday', 5: 'Saturday', 6: 'Sunday'}

def month_quiz(req):

    req.write("What month is it?<P>\n")

    for code, name in monthmap.items():

        req.write('<A HREF="%s?month=%d">%s</A><BR>' % (req.uri,

                    code, name))

def day_quiz(req):

    month = time.localtime()[1]

    req.write("What day is it?<P>\n")

    for code, name in daymap.items():

        req.write('<A HREF="%s?month=%d&day=%d">%s</A><BR>' % \

                   (req.uri, month, code, name))

def check_month_answer(req, answer):

    month = time.localtime()[1]

    if int(answer) == month:

        req.write("Yes, this is <B>%s</B>.<P>\n" % monthmap[month])

        return 1

    else:

        req.write("Sorry, you're wrong. Try again:<P>\n")

        month_quiz(req)

        return 0

def check_day_answer(req, answer):

    day = time.localtime()[6]

    if int(answer) == day:

        req.write("Yes, this is <B>%s</B>.\n" % daymap[day])

        return 1

    else:

        req.write("Sorry, you're wrong. Try again:<P>\n")

        day_quiz(req)

        return 0

def handler(req):

    req.content_type = "text/html"

    if req.header_only:

        return apache.OK

   

    req.write("""<HTML>

<HEAD>

<TITLE>mod_python GET Example</TITLE></HEAD><BODY>""")

    form = util.FieldStorage(req)

   

    if form.getfirst('month') == None:

        month_quiz(req)

    elif form.getfirst('day') == None:

        ismonthright = check_month_answer(req, form.getfirst('month'))

        if ismonthright:

            day_quiz(req)

    else:

        ismonthright = check_month_answer(req, form.getfirst('month'))

        if ismonthright:

            check_day_answer(req, form.getfirst('day'))

    

     req.write("</BODY></HTML>\n")

     return apache.OK

在这里,我使用了mod_python的util.FieldStorage类来解析GET请求。这个类被设计成尽可能和CGI的FieldStorage类兼容。事实上,在第18章中,使用GET的CGI例子中的表单不用做任何修改,就可以用在这里。对于这个程序来说,它不关心数据是由表单提交的,还是像这个例子中,通过手工产生的URL提交的。

还请注意,在这个程序中,req.uri保存着Python脚本本身的名称,这和pathinfo.py那个例子不同。当使用pathinfo输入的风格,Apache虽然不从req.uri中取得输入的数据,但是它会在您使用表单提交GET方法时这样做。因此,这个例子不需要getscriptname()函数。

如果您用过本章前面介绍的Apache配置文件的例子,您就可以通过http://localhost/py/ get.prog这个地址来运行这个例子。接口将和pathinfo.py那个例子一样。

19.5.3  POST方法

POST方法通过外在方式取得HTML表单提交的数据。相对于GET方法,它的主要优点是可以处理大容量的数据。有时,不能把POST结果添加到地址簿也是一个优点,比如您正处理敏感数据的时候。下面是另外一个版本询问月份和日期的例子,这次使用的是mod_python的POST方法,代码如下:

# mod_python POST example -- Chapter 19 -- post.py

from mod_python import apache, util

import time

import cgi, time, os

monthmap = {1: 'January', 2: 'February', 3: 'March', 4: 'April', 5: 'May',

    6: 'June', 7: 'July', 8: 'August', 9: 'September', 10: 'October',

    11: 'November', 12: 'December'}

daymap = {0: 'Monday', 1: 'Tuesday', 2: 'Wednesday', 3: 'Thursday',

    4: 'Friday', 5: 'Saturday', 6: 'Sunday'}

def month_quiz(req):

    req.write("What month is it?<P>\n")

    req.write('<FORM METHOD="POST" ACTION="%s">' % req.uri)

    for code, name in monthmap.items():

        req.write('<INPUT NAME="month" TYPE="radio" VALUE="%d"> %s<BR>' % \

                   (code, name))

    req.write('<INPUT TYPE="submit" NAME="submit" VALUE="Next  &gt;&gt;">')

    req.write("</FORM>\n")

def day_quiz(req):

    month = time.localtime()[1]

    req.write("What day is it?<P>\n")

    req.write('<FORM METHOD="POST" ACTION="%s">' % req.uri)

    req.write('<INPUT TYPE="hidden" NAME="month" VALUE="%d">' % month)

    for code, name in daymap.items():

    req.write('<INPUT NAME="day" TYPE="radio" VALUE="%d"> %s<BR>' % \

               (code, name))

    req.write('<INPUT TYPE="submit" NAME="submit" VALUE="Next  &gt;&gt;">')

    req.write("</FORM>\n")

def check_month_answer(req, answer):

    month = time.localtime()[1]

    if int(answer) == month:

        req.write("Yes, this is <B>%s</B>.<P>\n" % monthmap[month])

        return 1

    else:

        req.write("Sorry, you're wrong. Try again:<P>\n")

        month_quiz(req)

        return 0

def check_day_answer(req, answer):

    day = time.localtime()[6]

    if int(answer) == day:

        req.write("Yes, this is <B>%s</B>.\n" % daymap[day])

        return 1

    else:

        req.write("Sorry, you're wrong. Try again:<P>\n")

        day_quiz(req)

        return 0

def handler(req):

    req.content_type = "text/html"

    if req.header_only:

        return apache.OK

        req.write("""<HTML>

<HEAD>

<TITLE>mod_python POST Example</TITLE></HEAD><BODY>""")

    form = util.FieldStorage(req)

    if form.getfirst('month') == None:

        month_quiz(req)

    elif form.getfirst('day') == None:

        ismonthright = check_month_answer(req, form.getfirst('month'))

        if ismonthright:

            day_quiz(req)

    else:

        ismonthright = check_month_answer(req, form.getfirst('month'))

        if ismonthright:

            check_day_answer(req, form.getfirst('day'))

    req.write("</BODY></HTML>\n")

    return apache.OK

这个程序和GET版本的例子使用完全一样的逻辑。事实上,唯一改变的地方是产生选择菜单的HTML代码。提交POST数据的方法和CGI脚本一样还要感谢FieldStorage的接口兼容性。

既然mod_python的FieldStorage很大程度上兼容CGI的FieldStorage,在CGI那章所介绍的处理数据的原则同样也适用于mod_python。

如果您用过本章前面介绍的Apache配置文件的例子,您就可以通过载入http://localhost/py/ post.prog来运行这个例子。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论