python系列学习五——web开发

来源:互联网 发布:纽约大学gpa算法 编辑:程序博客网 时间:2024/05/01 00:42

1. 前言

    一个教练下面有一群学员,教练想把学员的成绩放到web平台上,分享给所有人查看。

2. 设计

    该web应用可能需要3个页面:一个“欢迎”页面,一个“选择选手”页面,以及一个“显示时间”页面

3. 开发

    好的web应用应当遵循MVC模式:

1)模型

建立AthleteList类,将文本数据转换为AthleteList对象实例。新建athletelist.py:

# coding=utf-8class AthleteList(list):    def __init__(self, a_name, a_dob=None, a_times=[]):        list.__init__([])        self.name = a_name        self.dob = a_dob        self.extend(a_times)        @staticmethod    def sanitize(the_time):        if '-' in the_time:            splitter = '-'        elif ':' in the_time:            splitter = ':'        else:            return the_time        (mins, secs) = the_time.split(splitter)        return mins + '.' + secs    # @property    def top3(self):        return sorted(set([self.sanitize(t) for t in self]))[0:3]

新建模块athletemodel.py:

#coding=utf-8import cPickle as pfrom athletelist import AthleteListdef get_coach_data(filename):    try:        with open(filename) as f:            data = f.readline().strip().split(',')            return AthleteList(data.pop(0), data.pop(0), data)    except IOError as err:        print 'File error: ' + str(err)        return Nonedef put_to_store(the_files):    athletes = {}    for f in the_files:        ath = get_coach_data(f)        athletes[ath.name] = ath    try:        with open('athletes.pickle' , 'w') as athp:            p.dump(athletes, athp)    except IOError as err:        print 'File error(put_to_store): ' + str(err)    return athletesdef get_from_store():    athletes = {}    try:        with open('athletes.pickle') as athp:            athletes = p.load(athp)    except IOError as err:        print 'File erro(get_from_store): ' + str(err)    return athletes

2)视图

模板引擎yate.py

#coding=utf-8"""从标准库的'string'模块导入'Template'类,它支持简单的字符串替换模板"""from string import Template# 该函数需要一个(可选)字符串作为参数,用来创建一个CGI行,默认值是:"text/html"def start_response(resp="text/html"):    return('Content-type: ' + resp + '\n\n')def include_header(the_title):    # 打开模板文件,读入文件内容,换入所提供的标题    with open('templates/header.html') as headf:        head_text = headf.read()    header = Template(head_text)    #subsitute()方法用来替换字符串中指定内容    return(header.substitute(title=the_title))def include_footer(the_links):    with open('templates/footer.html') as footf:        foot_text = footf.read()    # 将链接字典转换为一个字符串,再换入模板    link_string = ''    for key in the_links:        link_string += '<a href="' + the_links[key] + '">' + key + '</a>    '    footer = Template(foot_text)    return(footer.substitute(links=link_string))#返回表单最前面的html,允许指定url和typedef start_form(the_url, form_type="POST"):    return('<form action="' + the_url + '" method="' + form_type + '">')# 返回表单末尾的html,允许定制submit的文本内容def end_form(submit_msg="Submit"):    return('<p></p><input type=submit value="' + submit_msg + '"></form>')# 给定一个单选按钮名和值,创建一个html单选组def radio_button(rb_name, rb_value):    return('<input type="radio" name="' + rb_name +                             '" value="' + rb_value + '"> ' + rb_value + '<br />')# 给定一个项列表,函数将该列表转换为一个html无序列表。每次迭代增加一个li元素def u_list(items):    u_string = '<ul>'    for item in items:        u_string += '<li>' + item + '</li>'    u_string += '</ul>'    return(u_string)# 创建并返回一个html标题标记,默认为2级标题def header(header_text, header_level=2):    return('<h' + str(header_level) + '>' + header_text +           '</h' + str(header_level) + '>')# 用html段落标记创建一个文本段def para(para_text):    return('<p>' + para_text + '</p>') 

3)用python构建一个web服务器

新建模块simple_httpd.py

#!/usr/local/bin/python#coding=utf-8# 导入http服务器和CGI模块from BaseHTTPServer import HTTPServerfrom CGIHTTPServer import CGIHTTPRequestHandler#指定一个端口 port = 8080#创建一个http服务器httpd = HTTPServer(('', port), CGIHTTPRequestHandler)#显示一个友好消息,并启动服务器print("Starting simple_httpd on port: " + str(httpd.server_port))httpd.serve_forever()
在终端执行该模块:


打开浏览器,在地址栏输入 http://localhost:8080,可直接进入webapp下的index.html页面。

同时,web服务器记录了web请求的运行日志:


4) 控制器

    推荐web应用目录结构

    webapp/                                     项目顶层文件夹,除了包含子文件夹,还包含web应用的index.html、favicon.ico、样式表以及不放在其他子文件夹的所有内容

                  cgi-bin/                         为web应用写的所有代码需要放在一个名为cgin-bin的文件夹中

                  data/                              存放数据的文件夹

                  images/                        存放web应用的图像文件

                  templates/                    存放web应用的模板文件


在cgi-bin目录中,新建选择选手页面generate_list.py:

#!/usr/local/bin/python#coding=utf-8import athletemodelimport yateimport globdata_files = glob.glob('data/*.txt')athletes = athletemodel.put_to_store(data_files)# genereate form print yate.start_response()print yate.include_header("Coach Kelly's list of Athletes")print yate.start_form("generate_timing_data.py")print yate.para("Select an athlete from the list to work with:")for item in athletes:    print yate.radio_button('athlete', athletes[item].name)print yate.end_form('Selete')print yate.include_footer({"Home":"/index.html"})

再建立显示时间页面generate_timing_data.py

#!/usr/local/bin/python#coding=utf-8import cgiimport athletemodelimport yateimport cgitbcgitb.enable()# get all form data, and store a dictionaryform_data = cgi.FieldStorage()# access a specify data from form dataathlete_name = form_data['athlete'].valueathletes = athletemodel.get_from_store()print yate.start_response()print yate.include_header("Coach Kelly's Timing Data")print yate.header("Athlete: " + athlete_name + ", DOB: "+ athletes[athlete_name].dob + ".")print yate.para("The top times for this athlete are: ")print yate.u_list(athletes[athlete_name].top3())    #如果top3()方法被指定为@property,访问时直接使用.top3print yate.include_footer({"Home":"/index.html",                             "Select another athlete": "generate_list.py"})

4. 调试

python标准库提供了一个CGI跟踪模块cgitb,弃用这个模块时,会在web浏览器上显示详细的错误消息。

在CGI脚本前面增加下面两行代码,启用python的CGI跟踪技术:

import cgitbcgitb.enable()


小结:

1)标准库string模块包括一个名为Template的类,它支持简单的字符串替换

2)标准库BaseHTTPServer、CGIHTTPServer(3.x版本合并为http.server)模块可以在python中建立一个简单的web服务器

3)标准库glob模块适合处理文件名列表

4)启用标准库cgitb时,允许在浏览器中查看CGI编码错误

5)使用cgi.FieldStorage()访问作为web请求发送给web服务器的数据,数据将作为一个python字典

6)@property修饰符,可以使类的方法表现的像是一个属性

原创粉丝点击