代碼地址: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 + '\n\n') 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()