Web框架html
Web框架本質python
衆所周知,對於全部的Web應用,本質上其實就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端。web
舉例:數據庫
#!/usr/bin/env python #coding:utf-8 import socket #導入單線程通信模塊 def handle_request(client): #發送內容函數 buf = client.recv(1024) #設置最大傳輸字節 client.sendall(bytes("HTTP/1.1 200 OK\r\n\r\n", encoding='utf-8')) #向客戶端發送內容,以字節形式發送 client.sendall(bytes("Hello, World歡迎訪問", encoding='utf-8')) #向客戶端發送內容 def main(): #建立通信函數 sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #建立服務端通信對象 sock.bind(('localhost',8082)) #在服務端設置服務端ip和端口 sock.listen(5) #監聽IP和端口,設置一個參數,表示最多鏈接排隊數量 while True: #循環 connection, address = sock.accept() #等待接收客戶端的請求,一旦有客戶端請求鏈接,就會返回兩個值,一個是鏈接對象,一個是客戶端的地址信息,因此須要兩個變量來接收 handle_request(connection) #執行handle_request函數,將客戶端請求鏈接傳入handle_request函數 connection.close() #關閉鏈接 if __name__ == '__main__': #wds系統下if __name__ == "__main__"才能建立進程,咱們調試不要緊,之後在Linux系統沒這個問題 main() #執行main函數
上述經過socket來實現了其本質,而對於真實開發中的python web程序來講,通常會分爲兩部分:服務器程序和應用程序。服務器程序負責對socket服務器進行封裝,並在請求到來時,對請求的各類數據進行整理。應用程序則負責具體的邏輯處理。爲了方便應用程序的開發,就出現了衆多的Web框架,例如:Django、Flask、web.py 等。不一樣的框架有不一樣的開發方式,可是不管如何,開發出的應用程序都要和服務器程序配合,才能爲用戶提供服務。這樣,服務器程序就須要爲不一樣的框架提供不一樣的支持。這樣混亂的局面不管對於服務器仍是框架,都是很差的。對服務器來講,須要支持各類不一樣框架,對框架來講,只有支持它的服務器才能被開發出的應用使用。這時候,標準化就變得尤其重要。咱們能夠設立一個標準,只要服務器程序支持這個標準,框架也支持這個標準,那麼他們就能夠配合使用。一旦標準肯定,雙方各自實現。這樣,服務器能夠支持更多支持標準的框架,框架也能夠使用更多支持標準的服務器。瀏覽器
因此,對於Web框架來講分爲兩類,一類是即包含了socket服務端,有包含了邏輯處理,一類是隻包含邏輯處理須要另外作socket服務端服務器
python標準庫提供的獨立WSGI服務器稱爲wsgiref。mvc
WSGI(Web Server Gateway Interface)是一種規範,它定義了使用python編寫的web app與web server之間接口格式,實現web app與web server間的解耦。app
wsgiref模塊,python標準庫提供的獨立WSGI服務器稱爲wsgiref,就是Web框架邏輯處理包含了socket服務端框架
注意:wsgiref模塊在python3以上版本有問題,在2.7上能夠使用,因此下面的列子在2.7上運行的socket
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server #引入wsgiref的make_server def RunServer(environ, start_response): #建立通信內容函數 start_response('200 OK', [('Content-Type', 'text/html')]) #HTML方式返回內容 return '<h1>Hello, web!</h1>' #返回內容 if __name__ == '__main__': httpd = make_server('', 8082, RunServer) #設置訪問端口,和通信內容函數 httpd.serve_forever() #執行通信函數
RunServer(environ, start_response)建立通信內容函數,裏面有兩個參數
environ裏面包含用戶的請求信息如ip等
start_response裏面包含返回信息
查看方式:
自定義Web框架
1、框架
經過python標準庫提供的wsgiref模塊開發一個本身的Web框架
根據用戶訪問的路徑,給出相應的內容
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server def index(): #函數返回字符串index return 'index' def login(): #login return 'login' URLS = { #設置一個字典,鍵爲路徑名稱,值爲函數名稱 "/index":index, "/login":login, } def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) url = environ['PATH_INFO'] #接收用戶訪問的路徑名稱 if url in URLS.keys(): #判斷用戶訪問路徑在URLS字典裏是否存在 furl = URLS[url] #若是存在經過下標拿到字典裏的函數名稱 ret = furl() #執行函數賦值給ret變量,至關於ret等於函數返回字符串 else: ret = "404" #若是不存在ret變量等於404 return ret #最後將ret變量返回給瀏覽器 if __name__ == '__main__': httpd = make_server('', 8082, RunServer) httpd.serve_forever()
2、模板引擎,和MVC
MVC框架,就是歸類後根據文件夾定義的名字
在上一步驟中,對於全部的login、index均返回給用戶瀏覽器一個簡單的字符串,在現實的Web請求中通常會返回一個複雜的符合HTML規則的字符串,因此咱們通常將要返回給用戶的HTML寫在指定文件中,而後再返回。如:
模板引擎歸類,歸類就是爲了之後方便管理
urls.py將映射文件信息寫在這個文件裏,之後要添加映射就在這裏寫
#!/usr/bin/env python #coding:utf-8 import controller # 映射文件 URLS = { #設置一個字典,鍵爲路徑名稱,值爲函數名稱 "/index":controller.index, "/login":controller.login, }
controller.py邏輯處理文件,根據用戶訪問路徑,給出對應的處理,之後要添加邏輯處理函數就寫在這裏
#!/usr/bin/env python #coding:utf-8 import os #引入os模塊 # 映射文件對應的函數 def index(): #函數返HTML文件內容 f = open(os.path.join('views','index.html'),'r') #拼接路徑,打開index.html data = f.read() #讀出html文件內容 f.close() #關閉打開的文件 return data def login(): f = open(os.path.join('views', 'login.html'),'r') data = f.read() f.close() return data
start.py模板引擎啓動文件,用於啓動模板引擎,通常不作修改
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server #導入wsgiref模塊裏的make_server方法 from urls import URLS #導入映射文件變量 def RunServer(environ, start_response): #定義RunServer函數,接收請求信息,和發送內容 start_response('200 OK', [('Content-Type', 'text/html')]) url = environ['PATH_INFO'] #接收用戶訪問的路徑名稱 if url in URLS.keys(): #判斷用戶訪問路徑在URLS字典裏是否存在 furl = URLS[url] #若是存在經過下標拿到字典裏的函數名稱 ret = furl() #執行函數賦值給ret變量,至關於ret等於函數返回字符串 else: ret = "404" #若是不存在ret變量等於404 return ret #最後將ret變量返回給瀏覽器 if __name__ == '__main__': httpd = make_server('', 8082, RunServer) httpd.serve_forever()
views文件夾用於專門存放html文件
models文件夾用於專門存放數據庫處理文件
整理後的結構
Web框架,通常根據存放數據庫處理文件夾的首字母M,存放html文件夾首字母V,邏輯處理文件首字母C,來命名的,這就是mvc框架
Web框架運行圖
Web框架請求動態內容
對於上述代碼,雖然能夠返回給用戶HTML的內容以現實複雜的頁面,可是仍是存在問題:如何給用戶返回動態內容?
1自定義一套特殊的語法,進行替換
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <!--{{item}}設置一個表示--> <h1>{{item}}</h1> </body> </html>
邏輯處理文件controller.py
#!/usr/bin/env python #coding:utf-8 import os #引入os模塊 import time #引入事件模塊 # 映射文件對應的函數 def index(): #函數返HTML文件內容 f = open(os.path.join('views','index.html'),'r') #拼接路徑,打開index.html data = f.read() #讀出html文件內容 f.close() #關閉打開的文件 new_data = data.replace("{{item}}",str(time.time())) #獲取系統時間轉換成字符串,替換html裏的{{item}} return new_data def login(): f = open(os.path.join('views', 'login.html'),'r') data = f.read() f.close() return data
2使用開源工具jinja2,遵循其指定語法
jinja2模塊Web框架模塊
Template()方法邏輯處理Web框架
render()方法設置html可調用python變量
encode()返回邏輯處理後的網頁字符串給瀏覽器
首先須要安裝jinja2第三方模塊
邏輯處理文件controller.py
#!/usr/bin/env python #coding:utf-8 import os #引入os模塊 from jinja2 import Template #引入jinja2模塊 # 映射文件對應的函數 def index(): #函數返HTML文件內容 f = open(os.path.join('views','index.html'),'r') #拼接路徑,打開index.html result = f.read() #讀出html文件內容 f.close() # 關閉打開的文件 template = Template(result) #將讀出的字符串傳入jinja2模塊的Template方法邏輯處理網頁字符串 data = template.render(name='John Doe', user_list=['alex', 'eric']) #render方法向網頁字符串添加python能夠變量 return data.encode('utf-8') #返回邏輯處理後的字符串給瀏覽器 def login(): f = open(os.path.join('views', 'login.html'),'r') data = f.read() f.close() return data
html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>{{name}}</h1> <!--{{引用框架邏輯處理設置變量}}--> <ul> {% for item in user_list %} <!--{%能夠遠行代碼塊%}--> <li>{{item}}</li> {% endfor %} </ul> </body> </html>