Python Web開發

欲乘風發表於2018-12-27

1、Web應用的5個步驟
①使用者在他所選擇的Web瀏覽器中輸入一個Web地址、選擇一個超連結,或者點選一個按鈕。
②Web瀏覽器將使用者的動作轉換為一個Web請求,並通過網際網路把它傳送到一個伺服器。
③Web伺服器收到Web請求,必須決定接下來做什麼。
④Web伺服器處理Web請求,建立一個Web響應,這會通過網際網路發回給等待著的Web瀏覽器。
⑤第④步(可能)有很多子步驟
實際上第4步,可能包括很多子步驟,這要看Web伺服器如何生成響應。如果伺服器所要做的只是找到靜態內容並把它發回給瀏覽器,那麼這些子步驟不會太費勁,因為這些都只是檔案I/O而已。
不過,如果必須生成動態內容,就要包括以下子步驟:Web伺服器要找到所要執行的程式、執行找到的程式,然後捕獲程式的輸出作為Web響應……再把它發回給還在等待的Web瀏覽器。早在Web發展的初期,這個生成動態內容的過程已經得到標準化,稱為通用閘道器介面(Common Gateway Interface,CGI)。符合標準的程式通常稱為CGI指令碼。
2、採用MVC設計Web應用
好的Web應用應當遵循模型-檢視-控制器(Model-View-Controller)模式,這有助於將Web應用的程式碼分解為易於管理的功能模組(或元件):
模型:儲存(以及有時處理)Web應用資料的程式碼。
檢視:格式化和顯示Web應用使用者介面的程式碼。
控制器:將Web應用“粘合”在一起並提供業務邏輯的程式碼。
通過遵循MVC模式,可以合理構建你的Web應用,從而當出現新的需求時能夠輕鬆擴充套件。另外還可以將工作分給多個人共同完成,每個人分別負責一個元件。
3、為資料建模
Web伺服器需要儲存資料的一個副本,在這裡資料就是Kelly教練的計時值。啟動這個Web應用時,需要把文字檔案中的資料轉換為AthleteList物件例項,儲存在一個字典中(按選手名索引),然後儲存為一個pickle檔案。下面把這個功能放在一個名為put _ to _ store()的新函式中。在Web應用執行時,pickle檔案中的資料可以作為一個字典應用使用。下面把這個功能放在另一個名為get _ from _store()的函式中。

class 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)
    def top3(self):
        return(sorted(set([santize(each_time)for each_time in self]))[0:3])

def get_coach_data(filename):
    try:
        with open(filename) as f:
            data=f.readline()
        temp1=data.strip().split(',')
        return AthleteList(temp1.pop(0),temp1.pop(0),temp1)
    except IOError as err:
        print('File error:'+str(err))
        return(None)
def santize(time_item):
        if '-' in time_item:
            splits='-'
        elif ':' in time_item:
            splits=':'

        else:
            return time_item
        (mins,secs)=time_item.split(splits)
        return(mins+'.'+secs)


import pickle
from athletelist import AthleteList
def get_coach_data(filename):
    try:
        with open(filename) as f:
            data=f.readline()
        temp1=data.strip().split(',')
        return AthleteList(temp1.pop(0),temp1.pop(0),temp1)
    except IOError as err:
        print('File error:'+str(err))
        return(None)
def put_to_store(files_list):
    all_athletes={}
    for each_file in files_list:
        ath=get_coach_data(each_file)
        all_athletes[ath.name]=ath
    try:
        with open('athletes.pickle','wb') as athf:
            pickle.dump(all_athletes,athf)
    except IOError as ioerr:
        print('File error(put_to_store):'+str(ioerr))

    return (all_athletes)
def get_from_store():
    all_athletes={}
    try:
        with open('athletes.pickle','rb') as athf:
            all_athletes=pickle.load(athf)
    except IOError as ioerr:
        print('File error(get_from_store):'+str(ioerr))
    return (all_athletes)
'''下面來測試程式碼,確保它能滿足要求,F5執行,以下是在IDLE視窗鍵入的'''
>>> the_files=['sarah2.txt','james2.txt','mikey2.txt','julie2.txt']
>>> data=put_to_store(the_files)
>>> data
{'Sarah Sweeney': ['2:58', '2.58', '2:39', '2-25', '2-55', '2:54', '2.18', '2:55', '2:55', '2:22', '2-21', '2.22'], 'James Lee': ['2-34', '3:21', '2.34', '2.45', '3.01', '2:01', '2:01', '3:10', '2-22', '2-01', '2.01', '2:16'], 'Mikey McManus': ['2:22', '3.01', '3:01', '3.02', '3:02', '3.02', '3:22', '2.49', '2:38', '2:40', '2.22', '2-31'], 'Julie Jones': ['2.59', '2.11', '2:11', '2:23', '3-10', '2-23', '3:10', '3.21', '3-21', '3.01', '3.02', '2:59']}
>>> for each_athlete in data:
    print(data[each_athlete].name+' '+data[each_athlete].dob)


Sarah Sweeney 2002-6-17
James Lee 2002-3-14
Mikey McManus 2002-2-24
Julie Jones 2002-8-17
>>> data_copy=get_from_store()
>>> for each_data in data_copy:
    print(data_copy[each_data].name+' '+data_copy[each_data].dob)


Sarah Sweeney 2002-6-17
James Lee 2002-3-14
Mikey McManus 2002-2-24
Julie Jones 2002-8-17

4、檢視介面
上面已經編寫了模型程式碼,下面來看看檢視程式碼,這會建立Web應用的使用者介面。在Web上,使用者介面用Web的標記技術HTML來建立。
YATE另外一個模板引擎


from string import Template

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)
    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>&nbsp;&nbsp;&nbsp;&nbsp;'
    footer = Template(foot_text)
    return(footer.substitute(links=link_string))

def start_form(the_url, form_type="POST"):
    return('<form action="' + the_url + '" method="' + form_type + '">')

def end_form(submit_msg="Submit"):
    return('<p></p><input type=submit value="' + submit_msg + '"></form>')

def radio_button(rb_name, rb_value):
    return('<input type="radio" name="' + rb_name +
                             '" value="' + rb_value + '"> ' + rb_value + '<br />')

def u_list(items):
    u_string = '<ul>'
    for item in items:
        u_string += '<li>' + item + '</li>'
    u_string += '</ul>'
    return(u_string)

def header(header_text, header_level=2):
    return('<h' + str(header_level) + '>' + header_text +
           '</h' + str(header_level) + '>')

def para(para_text):
    return('<p>' + para_text + '</p>') 

5、控制你的程式碼
模型程式碼已經準備好,而且用yate模組幫助建立檢視程式碼,現在該用控制器程式碼把它們粘合在一起了。
首要的事情是你要合理的安排Web程式碼的目錄結構,保證它有條理有組織,這樣有利於以後增強擴充套件Web應用的能力。
這裡寫圖片描述
6、CGI讓Web伺服器執行程式
通用閘道器介面(CGI)是一個Internet標準,允許Web伺服器執行一個伺服器端程式,稱為CGI指令碼。一般的CGI指令碼放在cgi-bin的特殊資料夾下,這樣Web伺服器才能知道哪裡找到CGI指令碼,有些作業系統中(主要是類UNIX的系統),CGI指令碼必須先設定為可執行,Web伺服器才能執行這些指令碼對Web請求做出響應。
實際上這個世界上的所有Web伺服器都支援CGI指令碼,但在這裡使用有些大材小用了,好在,Python提供了它自己的Web伺服器,這個Web伺服器包含在http.server庫模組中。請檢視webapp.zip下載包的內容:它提供了一個支援CGI的Web伺服器,名為simple_httpd.py

'''用python構建web伺服器必須有這5行程式碼'''
from http.server import HTTPServer, CGIHTTPRequestHandler
'''匯入http伺服器和CGI模組'''
port = 8080
'''指定一個埠'''
httpd = HTTPServer(('', port), CGIHTTPRequestHandler)
'''建立http伺服器'''
print("Starting simple_httpd on port: " + str(httpd.server_port))
httpd.serve_forever()
'''顯示友好的訊息並啟動伺服器'''

7、顯示選手列表
這裡寫圖片描述
建立一個名為generate_list.py的程式

import athletemodel
import yate
import glob
'''利用glob可以向作業系統查詢一個檔名列表'''

data_files=glob.glob("data/*.txt")
athletes=athletemodel.put_to_store(data_files)

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("Selecct an athlete from the list to work with:"))
for each_athlete in athletes:
    print(yate.radio_button("which_athlete",athletes[each_athlete].name))
print(yate.end_form("Select"))
print(yate.include_footer({"Home":"/index.html"}))

8、建立另一個CGI指令碼generate _ timing_data.py
生成一個新的HTML頁面,其中包含所選選手的前3個時間。
這裡寫圖片描述

import athletemodel
import yate
import cgi
import cgitb
cgitb.enable()

athletes=athletemodel.get_from_store()
form_data=cgi.FieldStorage()
'''獲取所有表單資料,並放在一個字典中'''
athlete_name=form_data['which_athlete'].value
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))
print(yate.include_footer({"Home":"/index.html","select another athlete":"generate_list.py"}))

9、測試驅動
為了測試CGI指令碼,需要啟動一個Web伺服器並執行。
從webapp資料夾開啟一個命令視窗,啟動你的web伺服器:
python.exe simplehttpd.py
這裡寫圖片描述
然後在瀏覽器上訪問:http://127.0.0.1:8080
這裡寫圖片描述
這裡寫圖片描述
這裡寫圖片描述
10、啟用CGI跟蹤來幫助解決錯誤
在CGI指令碼前面增加這兩行程式碼啟用python的cgi跟蹤技術:
import cgitb
cgitb.enable()
注:
如果一個方法使用了@property修飾符,那麼這個方法會被看成是一個類屬性,所以訪問的時候不必加括號了

相關文章