代码地址:https://files.cnblogs.com/files/ceshixuexi/HeadFristPython.zip
一般以MVC模式开发
M:模型,存储web应用的代码
V:视图,格式化和显示web应用用户界面的代码
C:控制器,将web应用“粘合”在一起并提供业务逻辑的代码
cgi-bin目录下:
1、athletelist.py:
1 class AthleteList(list): 2 3 def __init__(self, a_name, a_dob=None, a_times=[]): 4 list.__init__([]) 5 self.name = a_name 6 self.dob = a_dob 7 self.extend(a_times) 8 9 @staticmethod # 静态方法 10 def sanitize(time_string): 11 if '-' in time_string: 12 splitter = '-' 13 elif ':' in time_string: 14 splitter = ':' 15 else: 16 return(time_string) 17 (mins, secs) = time_string.split(splitter) 18 return(mins + '.' + secs) 19 20 @property # 这个修饰符可以将方法看做类属性 21 def top3(self): 22 return(sorted(set([self.sanitize(t) for t in self]))[0:3])
2、athletemodel.py
1 import pickle 2 3 from athletelist import AthleteList 4 5 def get_coach_data(filename): 6 try: 7 with open(filename) as f: 8 data = f.readline() 9 templ = data.strip().split(',') 10 return(AthleteList(templ.pop(0), templ.pop(0), templ)) 11 except IOError as ioerr: 12 print('File error (get_coach_data): ' + str(ioerr)) 13 return(None) 14 15 def put_to_store(files_list): 16 all_athletes = {} 17 for each_file in files_list: 18 ath = get_coach_data(each_file) 19 all_athletes[ath.name] = ath 20 try: 21 with open('athletes.pickle', 'wb') as athf: 22 pickle.dump(all_athletes, athf) 23 except IOError as ioerr: 24 print('File error (put_and_store): ' + str(ioerr)) 25 return(all_athletes) 26 27 def get_from_store(): 28 all_athletes = {} 29 try: 30 with open('athletes.pickle', 'rb') as athf: 31 all_athletes = pickle.load(athf) 32 except IOError as ioerr: 33 print('File error (get_from_store): ' + str(ioerr)) 34 return(all_athletes)
3、generate_list.py
1 import glob 2 import athletemodel 3 import yate 4 5 6 data_files = glob.glob('data/*.txt') 7 athletes = athletemodel.put_to_store(data_files) 8 9 print(yate.start_response()) 10 print(yate.include_header("Coach Kelly's List of Athletes")) 11 print(yate.start_form("generate_timing_data.py")) 12 print(yate.para('Select an athlete from the list to work with:')) 13 for each_athlete in athletes: 14 print(yate.radio_button("which_athlete", athletes[each_athlete].name)) 15 print(yate.end_form("Select")) 16 print(yate.include_footer({'Home': '/index.html'}))
4、yate.py
1 from string import Template 2 # 从标准库string中导入Temlate类 3 4 5 def start_response(resp="text/html"): 6 return('Content-type: ' + resp + ' ') 7 # 这个函数需要一个可选的字符串作为参数,用它来创建一个CGI“content-type:”行,参数缺省值为“text/html” 8 9 def include_header(the_title): 10 with open('templates/header.html') as headf: 11 # 打开模板文件,读入文件,换入所提供的标题 12 head_text = headf.read() 13 header = Template(head_text) 14 return(header.substitute(title=the_title)) 15 # 这个函数需要一个字符串作为参数,用在html页面最前面的标题中。页面本身存储在一个单独的文件“templates/header.html” 16 # 可以根据需要替换标题 17 18 def include_footer(the_links): 19 with open('templates/footer.html') as footf: 20 foot_text = footf.read() 21 link_string = '' 22 # 换入链接字典 23 for key in the_links: 24 # 将链接字典转换为一个字符串,然后换入模板 25 link_string += '<a href="' + the_links[key] + '">' + key + '</a> ' 26 footer = Template(foot_text) 27 return(footer.substitute(links=link_string)) 28 # 与include_header函数一样,这个函数使用一个字符串作为参数,来创建htm页面的尾部 29 # 页面本身存储在"template/footer"中,参数用于动态地创建一组html链接标记。从这些标记看,参数应该是一个字典 30 31 def start_form(the_url, form_type="POST"): # 这一般是post或者get 32 return('<form action="' + the_url + '" method="' + form_type + '">') 33 # 这个函数返回表单最前面的html,允许调用者指定url,还可以指定所要使用的方法 34 35 def end_form(submit_msg="Submit"): 36 return('<p></p><input type=submit value="' + submit_msg + '"></form>') 37 # 这个函数返回的表单末尾的html标记,同时还允许调用着制定表单“submit”按钮的文本 38 39 def radio_button(rb_name, rb_value): 40 return('<input type="radio" name="' + rb_name + 41 '" value="' + rb_value + '"> ' + rb_value + '<br />') 42 # 给定一个单选按钮名和值,创建一个html单选按钮(通常包括在一个html表单中)。注意:2个参数都是必要的 43 44 def u_list(items): 45 u_string = '<ul>' 46 for item in items: 47 # 一个简单的for循环就可以达到目的 48 u_string += '<li>' + item + '</li>' 49 u_string += '</ul>' 50 return(u_string) 51 # 给定一个项列表,这个函数会把该列表转换为一个html无序列表。一个简单的for循环就可以达到目的 52 53 def header(header_text, header_level=2): 54 return('<h' + str(header_level) + '>' + header_text + 55 '</h' + str(header_level) + '>') 56 # 创建并返回一个html标题标记(h1,h2,h3等),默认为h2级标题。“header_text”参数是必要的 57 58 def para(para_text): 59 return('<p>' + para_text + '</p>') 60 # 文本
5、generate_timing_data.py
1 #! /usr/local/bin/python3 2 3 import cgi 4 5 import cgitb 6 cgitb.enable() 7 #这两行代码启用python的CGI跟踪技术 8 9 import athletemodel 10 import yate 11 12 13 14 15 16 athletes = athletemodel.get_from_store() 17 # 从模型获得数据 18 19 form_data = cgi.FieldStorage() 20 #所有表单数据,并放到一个字典中 21 22 athlete_name =form_data['which_athlete'].value 23 #从表单数据中访问一个指定的数据 24 25 print(yate.start_response()) 26 print(yate.include_header("Coach Kelly's Timing Data")) 27 print(yate.header("Athlete: " + athlete_name + ", DOB: " + 28 athletes[athlete_name].dob + ".")) 29 print(yate.para("The top times for this athlete are:")) 30 print(yate.u_list(athletes[athlete_name].top3)) 31 print(yate.include_footer({'Home':"/index.html", 32 "Select anthor athlete:":"generate_list.py"}))
http.py
from http.server import HTTPServer, CGIHTTPRequestHandler port = 8002 httpd = HTTPServer(('', port), CGIHTTPRequestHandler) print("Starting simple_httpd on port: " + str(httpd.server_port)) httpd.serve_forever()