10 分離式web框架css
將http請求封裝成以鍵值對的形式封裝成字典environ:html
"PATH_INFO"對應的值爲請求文件路徑,python
「QUERY_STRING」對應的值爲get請求發送的數據mysql
「REQUEST+METHOD」對應的值爲請求方式。jquery
同時封裝一個發送響應格式的函數start_server;經過特定的方式return [ ]返回數據並調用內置方法返回給瀏覽器。web
請求參數的獲取:sql
GET請求參數的傳遞在url請求文件路徑後邊拼接顯式傳輸,能夠直接在wsgiref模塊封裝好的environ請求信息字典中以鍵「QUERY_STRING」取值獲取傳遞的參數;數據庫
POST請求參數的傳遞是在請求信息的請求數據部分,瀏覽器
經過在wsgiref模塊封裝好的environ請求信息字典中以鍵「CONTENT_LENGTH」獲取參數(bytes類型)長度,而後經過environ["wsgi.input"].read(長度)獲取傳遞的參數(bytes類型)服務器
請求參數的處理:
內置模塊(from urllib.parse import parse_qs)
執行parse_qs()進行格式化成字典找到對應的參數值(列表形式,注意get爲字符串,post爲字節);
具體處理方式:
GET:
query_string=environ["QUERY_STRING"] |
#'QUERY_STRING': 'username=zhangsan&userpsd=abc', |
query_string=parse_qs(query_string) |
#{ 'username':['zhangsan'],'userpsd':['abc']} |
name=query_request["username"][0] |
'zhangsan' |
psd=query_request["userpsd"][0] |
'abc' |
POST:
leng=int(environ.get('CONTENT_LENGTH',0)) |
#'CONTENT_LENGTH'參數長度 |
query_string=environ['wsgi.input'].read(leng) |
#{ 'username':['zhangsan'],'userpsd':['abc']} |
query_string=parse_qs(query_string) |
#{ b'username':[b'zhangsan'],b'userpsd':[b'abc']} |
name=query_string[b'username'][0].decode("utf-8") |
'zhangsan' |
psd=query_string[b'userpsd'][0].decode("utf-8") |
'abc' |
wsgiref封裝的請求信息:
GET |
{……. 'SERVER_PORT': '8888', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'SERVER_SOFTWARE': 'WSGIServer/0.2', 'REQUEST_METHOD': 'GET', 'PATH_INFO': '/auth', 'QUERY_STRING': 'username=zhangsan&userpsd=abc', 'REMOTE_ADDR': '127.0.0.1', 'CONTENT_TYPE': 'text/plain', 'HTTP_HOST': '127.0.0.1:8888', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'wsgi.input': <_io.BufferedReader name=916>…….} |
POST |
{…… 'GATEWAY_INTERFACE': 'CGI/1.1', 'SERVER_PORT': '8888', 'REMOTE_HOST': '', 'CONTENT_LENGTH': '29', 'SCRIPT_NAME': '', 'SERVER_PROTOCOL': 'HTTP/1.1', 'REQUEST_METHOD': 'POST', 'PATH_INFO': '/auth', 'QUERY_STRING': '', 'HTTP_ACCEPT_LANGUAGE': 'zh-CN,zh;q=0.9', 'wsgi.input': <_io.BufferedReader name=880>, 'wsgi.errors': <_io.TextIOWrapper name='<stderr>' mode='w' encoding='UTF-8'>, 'wsgi.version': (1, 0), 'wsgi.run_once': False, 'wsgi.url_scheme': 'http', 'wsgi.multithread': True, 'wsgi.multiprocess': False, 'wsgi.file_wrapper': <class 'wsgiref.util.FileWrapper'>} |
在瀏覽器地址欄直接輸入地址端口:127.0.0.1:8888
manege.py:
1 from wsgiref.simple_server import make_server #python內置基於socket的服務程序模塊 2 from urls import func_mappers #本身封裝的請求文件路徑與對應操做映射模塊 3 4 def application(environ,start_reponse): 5 """ 6 基於wsgiref模塊實現客戶端請求數據的封裝(字典environ)和封裝的響應格式發送函數(statr_response)進行服務響應 7 :param environ: wsgiref模塊封裝好的請求信息字典 8 :param start_reponse: wsgiref模塊封裝的響應格式發送函數 9 :return: 10 """ 11 path=environ["PATH_INFO"] #經過字典取值獲取請求路徑信息 12 start_reponse("200 Ok",[("Content","text/html")]) #分裝好的函數發送響應格式信息 13 # print(path) 14 # 根據請求文件路徑,映射與之對應的函數操做 15 for mapper in func_mappers: 16 if path==mapper[0]: 17 data=mapper[1](environ) 18 else: 19 data=b"Sorry:404 not find" 20 return [data] 21 22 if __name__ == '__main__': 23 httpd=make_server("127.0.0.1",8888,application) 24 httpd.serve_forever()
modles.py
1 # 鏈接數據庫,建立須要實用的信息表 2 import pymysql 3 conn=pymysql.connect("127.0.0.1","root","","web") 4 cursor=conn.cursor() 5 6 user=[("zhangsan","abc"), 7 ("lisi","123")] 8 sql_createTable="create table userinfo(uid int primary key auto_increment,name char(12) unique not null ,password char(32) not null )" 9 sql_insret="insert into userinfo(name,password) values" 10 11 cursor.execute(sql_createTable) 12 13 for data in user: 14 sql_value=sql_insret+str(data) 15 cursor.execute(sql_value) 16 conn.commit() 17 18 cursor.close() 19 conn.close()
urls.py
1 # 路由信息:請求文件路徑與對應操做函數的映射表 2 from views import * 3 func_mappers=[ 4 ("/",func_login), 5 ("/auth",func_auth)]
views.py
1 from urllib.parse import parse_qs #內置模塊方法用於處理請求傳遞的數據格式 2 from webauth import auth 3 4 # 客戶端請求根目錄時響應登陸頁面 5 def func_login(environ): 6 with open("login.html", "rb")as f: 7 data = f.read() 8 return data 9 10 # 客戶端提交登陸時,判斷請求方式,獲取提交的數據,進行驗證 11 def func_auth(environ): 12 13 if environ.get("REQUEST_METHOD") == "GET": 14 query_request = environ["QUERY_STRING"] 15 # print(user) 16 # print(environ) 17 18 query_request = parse_qs(query_request) 19 print(repr(query_request)) 20 username = query_request["username"][0] 21 psd = query_request["userpsd"][0] 22 23 elif environ.get("REQUEST_METHOD") == "POST": 24 # 獲取請求體數據的長度,由於提交過來的數據須要用它來提取,注意POST請求和GET請求的獲取數據的方式不一樣 25 try: 26 request_body_size = int(environ.get('CONTENT_LENGTH', 0)) 27 except (ValueError): 28 request_body_size = 0 29 # POST請求獲取數據的方式 30 request_data = environ['wsgi.input'].read(request_body_size) 31 print('>>>>>', request_data) # >>>>> b'username=chao&password=123',是個bytes類型數據 32 print('?????', environ['QUERY_STRING']) # ????? 空的,由於post請求只能按照上面這種方式取數據 33 # parse_qs能夠幫咱們解析數據 34 re_data = parse_qs(request_data) 35 print('拆解後的數據', re_data) # 拆解後的數據 {b'password': [b'123'], b'username': [b'chao']} 36 username=re_data[b'username'][0].decode("utf-8") 37 psd=re_data[b'userpsd'][0].decode("utf-8") 38 39 # 獲取用戶名和密碼以後進行提交驗證 40 status = auth(username, psd) 41 if status: 42 with open("login_success.html", "rb")as f: 43 data = f.read() 44 else: 45 data = "<h1> login error</h1>".encode("utf-8") 46 return data
webauth.py
1 # 登陸認證使用:鏈接數據庫查詢用戶名和密碼進行檢驗 2 def auth(username,psd): 3 import pymysql 4 conn = pymysql.connect("127.0.0.1", "root", "", "web") 5 cursor = conn.cursor() 6 sql_select=f"select * from userinfo where name='{username}' and password='{psd}' " 7 # print(sql_select) 8 ret=cursor.execute(sql_select) #函數返回結果ret爲匹配到的記錄條數 9 cursor.close() 10 conn.cursor() 11 return ret 12 # print(auth('zhangsan','abc'))
login.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <link rel="icon" href="faviron.ico"> 6 <title>登陸</title> 7 </head> 8 <body> 9 <div> 10 11 <form action="auth" method="post" name="login"><!--以post請求方式auth驗證--> 12 13 <!--<form action="auth" method="get" name="login"><!–以get請求方式auth驗證–>--> 14 <table> 15 <tr> 16 <td><label for="username">用戶名</label></td> 17 <td><input type="text" name="username" id="username"></td> 18 </tr> 19 <tr> 20 <td> <label for="userpsd">密碼</label></td> 21 <td><input type="password" name="userpsd" id="userpsd"></td> 22 </tr> 23 <tr> 24 <td ><input type="reset"></td> 25 <td ><input type="submit"></td> 26 </tr> 27 </table> 28 29 </form> 30 </div> 31 </body> 32 <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> 33 <script> 34 $(function () { 35 //在登陸以前在客戶端進行帳號、密碼初級判斷 36 $("form[name='login']").submit (function () { 37 var name = $("#username").val(); 38 var psd = $("#userpsd").val(); 39 40 if (name == "" || psd == "") { 41 alert("用戶名和密碼不能爲空!"); 42 return false 43 } 44 }) 45 }) 46 </script> 47 </html>
login_success.html
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"> 5 <meta http-equiv="refresh" content=""> 6 <meta name="keywords" content=""> 7 <style></style> 8 <script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.js"></script> 9 <link rel="stylesheet" href=""> 10 <title>首頁</title> 11 </head> 12 <body> 13 <div> 14 <h1>登陸成功!</h1> 15 </div> 16 </body> 17 </html>