說明:該篇博客是博主一字一碼編寫的,實屬不易,請尊重原創,謝謝你們!javascript
目錄css
一丶項目說明html
二丶數據準備 java
三丶使用網絡TCP開發一個基於WSGI協議的Web服務器python
五丶在框架中實現添加股票功能jquery
七丶在框架中實現修改股票功能ajax
1.實現過程正則表達式
用戶經過瀏覽器向Web服務器請求資源,Web服務器基於WSGI協議調用Web框架中application接口函數,在application函數中根據用戶請求地址,匹配路由規則,匹配成功後調用請求地址對應的視圖函數,在視圖函數中主要操做爲對MySQL數據庫的增刪改查以及讀取html頁面模板內容,而後將模板中須要填充的數據與MySQL返回的數據進行字符串拼接,而後返回給Web服務器,最終Web服務器將拿到的數據看成響應體數據,並與狀態碼和響應頭進行拼接後返回給瀏覽器,在瀏覽器上呈現用戶想要看到的資源數據
2.最終效果展現
3.效果動圖
1.在MySQL中建立stock_db數據庫
create database stock_db charset=utf8;
2.在stock_db數據庫下建立股票信息表info
3.在stock_db數據庫下建立關注信息表focus
4.向focus表中的info_id字段添加info表的id外鍵
5.插入表數據
INSERT INTO `info` VALUES (1,'000007','全新好','10.01%','4.40%',16.05,14.60,'2019-03-18'),(2,'000036','華聯控股','10.04%','10.80%',11.29,10.26,'2019-03-20'),(3,'000039','中集集團','1.35%','1.78%',18.07,18.06,'2019-02-28'),(4,'000050','深天馬A','4.38%','4.65%',22.86,22.02,'2019-03-19'),(5,'000056','皇庭國際','0.39%','0.65%',12.96,12.91,'2019-03-20'),(6,'000059','華錦股份','3.37%','7.16%',12.26,12.24,'2018-12-11'),(7,'000060','中金嶺南','1.34%','3.39%',12.08,11.92,'2019-03-20'),(8,'000426','興業礦業','0.41%','2.17%',9.71,9.67,'2019-03-20'),(9,'000488','晨鳴紙業','6.30%','5.50%',16.37,15.59,'2019-03-10'),(10,'000528','柳工','1.84%','3.03%',9.42,9.33,'2019-03-19'),(11,'000540','中天金融','0.37%','5.46%',8.11,8.08,'2019-03-20'),(12,'000581','威孚高科','3.49%','3.72%',27.00,26.86,'2019-02-26'),(13,'000627','天茂集團','5.81%','12.51%',10.93,10.33,'2019-03-20'),(14,'000683','遠興能源','6.42%','21.27%',3.48,3.29,'2019-03-19'),(15,'000703','恆逸石化','0.24%','1.65%',16.92,16.88,'2019-03-20'),(16,'000822','山東海化','6.60%','8.54%',9.05,8.75,'2019-03-06'),(17,'000830','魯西化工','1.38%','4.80%',7.36,7.26,'2019-03-20'),(18,'000878','雲南銅業','1.26%','3.23%',14.50,14.47,'2019-03-19'),(19,'000905','廈門港務','5.44%','10.85%',15.90,15.60,'2018-12-20'),(20,'000990','誠志股份','0.53%','1.00%',16.99,16.90,'2019-03-20'),(21,'002019','億帆醫藥','1.19%','2.81%',17.05,16.85,'2019-03-20'),(22,'002078','太陽紙業','2.05%','1.90%',8.45,8.29,'2019-03-19'),(23,'002092','中泰化學','7.25%','6.20%',15.53,14.48,'2019-03-20'),(24,'002145','中核鈦白','2.43%','7.68%',6.75,6.61,'2019-03-19'),(25,'002285','世聯行','8.59%','5.66%',9.23,8.50,'2019-03-20'),(26,'002311','海大集團','1.13%','0.24%',18.81,18.63,'2019-03-19'),(27,'002460','贛鋒鋰業','9.41%','9.00%',63.70,58.22,'2019-03-20'),(28,'002466','天齊鋰業','3.62%','3.66%',68.44,66.05,'2019-03-20'),(29,'002470','金正大','2.30%','0.99%',8.00,7.82,'2019-03-20'),(30,'002496','輝豐股份','3.15%','4.29%',5.24,5.08,'2018-12-10'),(31,'002497','雅化集團','0.38%','12.36%',13.10,13.05,'2019-03-20'),(32,'002500','山西證券','0.44%','3.70%',11.49,11.44,'2019-03-20'),(33,'002636','金安國紀','2.70%','11.59%',19.80,19.42,'2019-03-19'),(34,'300032','金龍機電','0.66%','0.72%',15.28,15.18,'2019-03-20'),(35,'300115','長盈精密','0.60%','0.59%',33.50,33.41,'2019-03-19'),(36,'300268','萬福生科','-10.00%','0.27%',31.77,13.57,'2018-12-10'),(37,'300280','南通鍛壓','3.31%','0.66%',32.20,32.00,'2018-12-11'),(38,'300320','海達股份','0.28%','0.82%',18.26,18.21,'2019-03-20'),(39,'300408','三環集團','1.69%','0.81%',23.42,23.17,'2019-03-19'),(40,'300477','合縱科技','2.84%','5.12%',22.10,22.00,'2019-03-12'),(41,'600020','中原高速','5.46%','4.48%',5.60,5.31,'2019-03-20'),(42,'600033','福建高速','1.01%','1.77%',4.00,3.99,'2019-02-26'),(43,'600066','宇通客車','4.15%','1.49%',23.08,23.05,'2019-02-13'),(44,'600067','冠城大通','0.40%','2.97%',7.56,7.53,'2019-03-20'),(45,'600110','諾德股份','2.08%','4.26%',16.16,15.83,'2019-03-20'),(46,'600133','東湖高新','9.65%','21.74%',13.64,12.44,'2019-03-20'),(47,'600153','建發股份','3.65%','2.03%',13.35,13.21,'2019-03-10'),(48,'600180','瑞茂通','2.20%','1.07%',14.86,14.54,'2019-03-20'),(49,'600183','生益科技','6.94%','4.06%',14.94,14.12,'2019-03-19'),(50,'600188','兗州煤業','1.53%','0.99%',14.56,14.43,'2019-03-19'),(51,'600191','華資實業','10.03%','11.72%',15.80,14.36,'2019-03-20'),(52,'600210','紫江企業','6.03%','10.90%',6.68,6.30,'2019-03-20'),(53,'600212','江泉實業','1.39%','1.78%',10.20,10.15,'2019-03-19'),(54,'600225','*ST松江','4.96%','2.47%',5.71,5.61,'2018-12-13'),(55,'600230','滄州大化','5.74%','13.54%',43.26,40.91,'2019-03-20'),(56,'600231','凌鋼股份','2.79%','3.77%',3.68,3.60,'2019-03-19'),(57,'600291','西水股份','10.02%','9.23%',34.71,31.55,'2019-03-20'),(58,'600295','鄂爾多斯','4.96%','12.62%',16.51,15.73,'2019-03-20'),(59,'600303','曙光股份','8.37%','14.53%',11.53,10.64,'2019-03-20'),(60,'600308','華泰股份','1.12%','2.66%',6.30,6.26,'2019-03-19'),(61,'600309','萬華化學','0.03%','1.78%',31.81,31.80,'2019-03-20'),(62,'600352','浙江龍盛','0.39%','1.85%',10.32,10.28,'2019-03-20'),(63,'600354','敦煌種業','7.89%','18.74%',9.44,8.75,'2019-03-20'),(64,'600408','安泰集團','1.98%','3.38%',4.13,4.12,'2018-12-13'),(65,'600409','三友化工','0.62%','3.78%',11.36,11.29,'2019-03-20'),(66,'600499','科達潔能','0.46%','3.94%',8.84,8.80,'2019-03-20'),(67,'600508','上海能源','3.26%','2.99%',13.32,13.01,'2019-03-19'),(68,'600563','法拉電子','0.32%','1.36%',53.67,53.50,'2019-03-20'),(69,'600567','山鷹紙業','0.76%','2.85%',3.98,3.96,'2019-03-19'),(70,'600585','海螺水泥','0.45%','0.61%',24.51,24.44,'2019-03-19'),(71,'600668','尖峯集團','4.35%','6.43%',18.70,18.36,'2018-12-13'),(72,'600688','上海石化','2.72%','0.91%',6.80,6.74,'2019-02-01'),(73,'600729','重慶百貨','5.70%','3.34%',27.45,27.13,'2019-02-28'),(74,'600739','遼寧成大','3.30%','3.50%',19.74,19.11,'2019-03-20'),(75,'600779','水井坊','3.85%','2.77%',29.39,28.30,'2019-03-20'),(76,'600781','輔仁藥業','8.61%','4.16%',23.46,21.89,'2019-01-02'),(77,'600801','華新水泥','4.00%','10.15%',12.99,12.49,'2019-03-20'),(78,'600846','同濟科技','2.06%','17.41%',9.39,9.26,'2018-12-13'),(79,'600884','杉杉股份','1.08%','3.53%',20.67,20.45,'2019-03-20'),(80,'600966','博彙紙業','2.89%','5.54%',6.41,6.28,'2019-03-19'),(81,'600971','恆源煤電','2.36%','8.81%',12.16,11.88,'2019-03-20'),(82,'601012','隆基股份','0.76%','1.30%',19.93,19.78,'2019-03-20'),(83,'601100','恆立液壓','4.78%','0.92%',19.31,18.97,'2019-03-13'),(84,'601101','昊華能源','4.03%','6.06%',11.10,10.80,'2019-03-19'),(85,'601216','君正集團','2.16%','2.26%',5.20,5.10,'2018-12-17'),(86,'601666','平煤股份','2.81%','6.14%',6.96,6.77,'2019-03-20'),(87,'601668','中國建築','2.39%','1.42%',10.70,10.45,'2019-03-20'),(88,'601678','濱化股份','0.13%','2.47%',7.92,7.91,'2019-03-20'),(89,'601918','新集能源','1.23%','3.11%',4.93,4.92,'2019-03-19'),(90,'603167','渤海輪渡','2.77%','3.34%',11.87,11.61,'2018-12-13'),(91,'603369','今世緣','3.34%','2.13%',14.24,13.78,'2019-03-20'),(92,'603589','口子窖','3.99%','1.84%',39.37,39.04,'2019-02-26'),(93,'603799','華友鈷業','2.38%','7.19%',67.46,65.89,'2019-03-20'),(94,'603993','洛陽鉬業','2.94%','2.50%',7.36,7.16,'2019-03-19'); INSERT INTO `focus` VALUES (1,'先試一試',30),(2,'很是穩',38),(3,'通常般',78),(12,'不咋地',80),(17,'',23);
6.查詢表數據
1.建立工程目錄以及文件
說明:dynamic目錄----存放動態資源,static目錄----存放靜態資源,templates目錄----存放模板文件
server.conf----服務器配置文件,web_server.py----服務器啓動文件
2.服務器文件web_server.py代碼實現
import socket import multiprocessing class WSGIServer(object): def __init__(self): pass def main(): pass if __name__ == '__main__': main()
self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.tcp_server_socket.bind(("", 7979)) self.tcp_server_socket.listen(128)
while True: client_socket, client_addr = self.tcp_server_socket.accept() # 使用進程中的子線程來完成客戶端的鏈接處理 p = multiprocessing.Process(target=self.handle_client, args=(client_socket,)) p.start() client_socket.close() tcp_server_socket.close()
def handle_client(client_socket): request_data = client_socket.recv(1024).decode("utf-8") print(request_data) request_lines = request_data.splitlines() # print(request_lines) result = re.match(r"[^/]+([^ ]*)", request_lines[0]) if result: # print(result.group(1)+"*"*10) file_name = result.group(1) try: with open("./html"+file_name, "rb") as f: server_response_body = f.read() except: server_response = "HTTP/1.1 404 NOT FOUND \r\n" server_response += "\r\n" server_response += "-----File Not Found-----" client_socket.send(server_response.encode("utf-8")) else: server_response_header = "HTTP/1.1 200 OK \r\n" server_response_header += "\r\n" client_socket.send(server_response_header.encode("utf-8")) client_socket.send(server_response_body) client_socket.close()
3.讓該TCP服務器遵循WSGI協議
def index(): return "this is index page!" def login(): return "this is login page!" def application(environ, start_response): pass
# 以.py爲結尾表示請求動態資源不然爲靜態資源 if not file_name.endswith(".py"): try: with open("../html"+file_name, "rb") as f: server_response_body = f.read() except: server_response = "HTTP/1.1 404 NOT FOUND \r\n" server_response += "\r\n" server_response += "-----File Not Found-----" client_socket.send(server_response.encode("utf-8")) else: server_response_header = "HTTP/1.1 200 OK \r\n" server_response_header += "\r\n" client_socket.send(server_response_header.encode("utf-8")) client_socket.send(server_response_body) else: """遵循WSGI協議""" # 1.導入定義的web_frame框架,模擬WSGI調用過程 import web_frame # 2.調用框架中的application方法 env = dict() # print(file_name) /index.py env["PATH_INFO"] = file_name #{'PATH_INFO':'/index.py'} body = web_frame.application(env, self.start_response) # print(body, env) server_response_header = "HTTP/1.1 %s \r\n" % self.status for temp in self.header: server_response_header += '%s:%s\r\n' %(temp[0], temp[1]) server_response_header += "\r\n" # server_response_body = "<h1 style='color:red;text-align:center'>這是動態資源 %s </h1>" % time.ctime() server_response_data = server_response_header + body client_socket.send(server_response_data.encode("utf-8")) client_socket.close()
# 3.定義start_response函數 def start_response(self, status, header): self.status = status self.header = [("server"," web_frame/1.0")] self.header += header
def application(environ, start_response): file_name = environ['PATH_INFO'] start_response('200 OK', [('Content-Type', ' text/html;charset=utf-8')]) if file_name == "/index.py": return index() elif file_name == "/login.py": return login() else: return '<h1 style="color:red;text-align:center">Hello World! 你好 中國!<h1>'
4.在瀏覽器中渲染出網頁模板文件
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>首頁 - 我的選股系統 V5.87</title> <link href="/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="navbar navbar-inverse navbar-static-top "> <div class="container"> <div class="navbar-header"> <button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a href="#" class="navbar-brand">選股系統</a> </div> <div class="collapse navbar-collapse" id="mymenu"> <ul class="nav navbar-nav"> <li class="active"><a href="/index.html">股票信息</a></li> <li><a href="/center.html">我的中心</a></li> </ul> </div> </div> </div> <div class="container"> <div class="container-fluid"> <table class="table table-hover" style="background-color: #f1fde1"> <tr style="background-color:#a6e22b;"> <th>序號</th> <th>股票代碼</th> <th>股票簡稱</th> <th>漲跌幅</th> <th>換手率</th> <th>最新價(元)</th> <th>前期高點</th> <th>前期高點日期</th> <th>添加自選</th> </tr> </table> {%content%} </div> </div> <script src="/js/bootstrap.min.js"></script> </body> </html>
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>我的中心 - 我的選股系統 V5.87</title> <link href="/css/bootstrap.min.css" rel="stylesheet"> </head> <body> <div class="navbar navbar-inverse navbar-static-top "> <div class="container"> <div class="navbar-header"> <button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a href="#" class="navbar-brand">選股系統</a> </div> <div class="collapse navbar-collapse" id="mymenu"> <ul class="nav navbar-nav"> <li ><a href="/index.html">股票信息</a></li> <li class="active"><a href="/center.html">我的中心</a></li> </ul> </div> </div> </div> <div class="container"> <div class="container-fluid"> <table class="table table-hover" style="background-color: #f1fde1"> <tr style="background-color:#a6e22b;"> <th>股票代碼</th> <th>股票簡稱</th> <th>漲跌幅</th> <th>換手率</th> <th>最新價(元)</th> <th>前期高點</th> <th style="color:red">備註信息</th> <th>修改備註</th> <th>刪除</th> </tr> {%content%} </table> </div> </div> <script src="/js/bootstrap.min.js"></script> </body> </html>
if not file_name.endswith(".html"): # print(self.static_path_+file_name) try: with open("./static" + file_name, "rb") as f: server_response_body = f.read() except: server_response = "HTTP/1.1 404 NOT FOUND \r\n" server_response += "\r\n" server_response += "-----File Not Found-----" client_socket.send(server_response.encode("utf-8")) else: server_response_header = "HTTP/1.1 200 OK \r\n" server_response_header += "\r\n" client_socket.send(server_response_header.encode("utf-8")) client_socket.send(server_response_body) else: """遵循WSGI協議""" # 1.導入定義的web_frame框架,模擬WSGI調用過程 import web_frame # 2.調用框架中的application方法 env = dict() # print(file_name) /index.html env["PATH_INFO"] = file_name #{'PATH_INFO':'/index.html'} env["page_num"] = 1 body = web_frame.application(env, self.start_response) # print(body, env) # print(body, "5555555555") server_response_header = "HTTP/1.1 %s \r\n" % self.status for temp in self.header: server_response_header += '%s:%s\r\n' %(temp[0], temp[1]) server_response_header += "\r\n" # server_response_body = "<h1 style='color:red;text-align:center'>這是動態資源 %s </h1>" % time.ctime() server_response_data = server_response_header + body client_socket.send(server_response_data.encode("utf-8")) client_socket.close()
if result: # print(result.group(1)+"*"*10) file_name = result.group(1) if file_name == "/": file_name = "/index.html" # print(file_name,"qwqwqwq")
def index(): with open("./templates/index.html",encoding="utf-8") as f: content = f.read() return content def center(): with open("./templates/center.html") as f: return f.read() def application(env, start_response): start_response('200 OK', [('Content-Type', 'text/html;charset=utf-8')]) file_name = env['PATH_INFO'] # file_name = "/index.html" if file_name == "/index.html": return index() elif file_name == "/center.html": return center() else: return '<h1 style="color:red;text-align:center">Hello World! 你好 中國!<h1>'
def run_forever(self): while True: client_socket, client_addr = self.tcp_server_socket.accept() # 使用進程中的子線程來完成客戶端的鏈接處理 p = multiprocessing.Process(target=self.handle_client, args=(client_socket,)) p.start() client_socket.close() # handle_client(client_socket) tcp_server_socket.close() def main(): WSGIServer().run_forever()
5.以解釋器 程序 端口號 框架名:方法,如python3 web_server.py 7979 web_frame:application運行此程序
{ "static_path":"./static", "dynamic_path":"./dynamic" }
with open("./server.conf") as f: config = eval(f.read())
port = int(sys.argv[1])
frame_app = sys.argv[2].split(':') frame_name = frame_app[0] app_name = frame_app[1]
sys.path.append(config["dynamic_path"]) frame = __import__(frame_name) #__import__方法以變量的值去導入模塊 返回對象 app = getattr(frame, app_name) # getattr返回函數
WSGIServer(port, app, config['static_path']).run_forever()
在__init__方法中
def __init__(self, port, app, static_path): self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) self.tcp_server_socket.bind(("", port)) self.tcp_server_socket.listen(128) self.application = app self.static_path = static_path
在handle_client方法中
"""遵循WSGI協議""" # 2.調用框架中的application方法 env = dict() # print(file_name) /index.py env["PATH_INFO"] = file_name #{'PATH_INFO':'/index.py'} env["page_num"] = 1 body = self.application(env, self.start_response) # print(body, env) # print(body, "5555555555") server_response_header = "HTTP/1.1 %s \r\n" % self.status for temp in self.header: server_response_header += '%s:%s\r\n' %(temp[0], temp[1]) server_response_header += "\r\n" # server_response_body = "<h1 style='color:red;text-align:center'>這是動態資源 %s </h1>" % time.ctime() server_response_data = server_response_header + body client_socket.send(server_response_data.encode("utf-8"))
1.在web_frame.py框架文件中,使用裝飾器完成路由功能
URL_FUNC_DICT = dict() def route(url): def set_func(func): # URL_FUNC_DICT["/index.html"] = index URL_FUNC_DICT[url] = func def call_func(*args, **kwargs): return func(*args, **kwargs) return call_func return set_func
@route("/index.html") def index(): with open("./templates/index.html",encoding="utf-8") as f: content = f.read() return content @route("/center.html") def center(): with open("./templates/center.html") as f: return f.read()
def application(env, start_response): start_response('200 OK', [('Content-Type', 'text/html;charset=utf-8')]) file_name = env['PATH_INFO'] try: return URL_FUNC_DICT[file_name]() except Exception as ret: return "產生了異常:%s" % str(ret)
2.讓路由支持正則匹配規則
for url, func in URL_FUNC_DICT.items(): # { # r"/index.html":index, # r"/center.html":center, # } ret = re.match(url, file_name) if ret: return func() else: return "請求的url(%s)沒有對應的函數...." % file_name
@route(r"/index.html") def index(): with open("./templates/index.html",encoding="utf-8") as f: content = f.read() return content @route(r"/center.html") def center(): with open("./templates/center.html") as f: return f.read()
3.將數據庫中的數據顯示到index.html以及center.html網頁中
def connect_db(sql): conn = connect(host="localhost",port=3306,user="root",password="mysql",database="stock_db",charset="utf8") cs = conn.cursor() cs.execute(sql) info_data = cs.fetchall() if sql.startswith("select"): conn.close() cs.close() else: conn.commit() cs.close() return info_data
with open("./templates/index.html", encoding="utf-8") as f: content = f.read() info_data = connect_db("select * from info;") info_template= """ <tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td> <input type="button" value="添加" id="toAdd" name="toAdd" systemidvaule="%s"> </td> </tr> """ html_data = "" for temp in info_data: html_data += info_template % (temp[0],temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7],temp[1]) #後面加的temp[1]股票代碼是爲了填充添加列systemidvaule得值 content = re.sub(r"\{%content%\}",html_data,content) return content
with open("./templates/center.html", encoding="utf-8") as f: content = f.read() info_data = connect_db("select i.code,i.short,i.chg,i.turnover,i.price,i.highs,f.not_info from info as i inner join focus as f on i.id = f.info_id;") info_template = """ <tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td> <a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span aria-hidden="true">⇋</span> 修改 </a> </td> <td> <input type="button" value="刪除" id="toDel" name="toDel" systemidvaule="%s"> </td> </tr> """ html_data = "" for temp in info_data: html_data += info_template % (temp[0],temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[0],temp[0]) content = re.sub(r"\{%content%\}",html_data,content) return content
4.將主頁index.html數據進行分頁顯示
page_template = """ <div class="pagenation"> <a href="#" id="up">上一頁</a> <a href="/index.html" class="active">1</a> <a href="/index.html?page=2">2</a> <a href="/index.html?page=3">3</a> <a href="/index.html?page=4">4</a> <a href="/index.html?page=5">5</a> <a href="/index.html?page=6">6</a> <a href="/index.html?page=7">7</a> <a href="/index.html?page=8">8</a> <a href="/index.html?page=9">9</a> <a href="#" id="next">下一頁</a> </div> """
content = re.sub(r"\{%page%\}",page_template,content)
<style type="text/css"> .pagenation{height:32px;text-align:center;font-size:0;margin:30px auto;} .pagenation a{display:inline-block;border:1px solid #d2d2d2;background-color:#f1e7f8;font-size:12px;padding:7px 10px;color:#666;margin:5px;text-decoration: none;} .pagenation .active{background-color:#fff;color:#43a200} .pagenation span{display: inline-block;font-size: 12px;} .pagenation a:hover{background-color: #9bb797} </style>
page_num = re.match(r".*page=(\d+)",request_lines[0]) if page_num: page_num = page_num.group(1) # print(type(page_num)) if file_name.endswith("page=%s" % page_num): env = dict() # print(file_name) /index.py env["PATH_INFO"] = "/index.html" # {'PATH_INFO':'/index.py'} env["page_num"] = page_num body = self.application(env, self.start_response)
def application(environ, start_response): file_name = environ['PATH_INFO'] page_num = environ["page_num"] start_response('200 OK', [('Content-Type', ' text/html;charset=utf-8')]) for url, func in URL_FUNC_DICT.items(): ret = re.match(url, file_name) # print(ret,"wwwwwwwwwwwwww") if ret: # print(ret.group(1)) return func(page_num) else: return "請求的url(%s)地址不存在..." % file_name
page_num = int(page_num) with open("./templates/index.html", encoding="utf-8") as f: content = f.read() total_page = connect_db("select count(*) from info;") if (page_num-1)*12 > total_page[0][0]: html_data = "<h1 style='color:red'>沒有更多的數據了.....</h1>" content = re.sub(r"\{%content%\}", html_data, content) content = re.sub(r"\{%page%\}", "", content) return content info_data = connect_db("select * from info limit %d,%d;" %((page_num-1)*12,12))
1.在index.html中編寫如下JS,點擊添加按鈕則向http://127.0.0.1:7979/add/code.html地址發送請求,其中code爲股票代碼,經過js中的attr方法獲取模板中systemIdvalue的值也就是股票代碼
<script type="text/javascript"> $(document).ready(function(){ $("input[name='toAdd']").each(function(){ var currentAdd = $(this); var code = $(this).attr("systemIdVaule"); currentAdd.click(function(){ code = $(this).attr("systemIdVaule"); // alert("/add/" + code + ".html"); $.get("/add/" + code + ".html", function(data, status){ alert("數據: " + data + "\n狀態: " + status); window.location.reload(); }); }); }); });
2.定義add_focus方法,用於數據庫處理操做,在js中經過ajax方法向http://127.0.0.1:7979/add/code.html地址發送請求,因此在application函數中須要將正則匹配成功後的對象,傳遞到add_foucs函數中,由於以前在作分頁時,傳遞了頁碼參數,因此該函數須要定義兩個形參來接收
@route(r"/add/(\d+)\.html") def add_focus(page_num, ret): pass
3.獲取股票代碼,並經過股票代碼的值向數據庫中focus表中添加此股票數據
# 1. 獲取添加按鈕觸發的ajax請求地址中的股票代碼 stock_code = ret.group(1) # print(stock_code) # 2.判斷獲取到的股票代碼是否存在 res = connect_db("select * from info where code = '%s'" % stock_code) if not res: return "非法請求<This stock does not exist>" # 3.判斷該股票是否已經關注 res = connect_db("select * from info as i inner join focus as f on i.id = f.info_id where i.code = '%s'" % stock_code) if res: return "該股票已經關注過了,請勿重複關注...." # 4.關注股票 connect_db("insert into focus(info_id) select id from info where code = '%s'" % stock_code) return "關注股票成功"
4.測試點擊第一支股票進行添加,顯示關注成功,查看數據庫focus表最後一條數據爲info_id爲1的,肯定添加成功
5.博主這裏以爲當某支股票添加成功後,在該股票信息上不該該出現添加的功能按鈕,因此須要在數據庫info表中添加一個字段is_add字段,默認爲0(未添加)反之爲1,添加成功後將focus表中的股票在info表中將is_add字段修改成1
6.在index函數中將input標籤中的id字段的值修改成toAdd_%s,並在最後面添加isadd字段,之因此要將id字段的值修改成非相同的值,是由於id不容許重複
info_template= """ <tr> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td>%s</td> <td> <input type="button" value="添加" id="toAdd_%s" name="toAdd" systemidvaule="%s" isadd=%s> </td> </tr> """ html_data += info_template % (temp[0],temp[1],temp[2],temp[3],temp[4],temp[5],temp[6],temp[7],temp[1],temp[1],temp[8])
7.在add_focus函數中在添加股票信息到focus以後須要將該股票對應的info表的is_add字段的值修改成1
connect_db("update info set is_add = 1 where code = '%s'" % stock_code)
8.回到index.html文件中js中,獲取模板中isadd的值,若是該值爲1表示已經關注,因此設置添加按鈕不顯示
var is_add = $(this).attr("isadd"); if(is_add == 1){ document.getElementById("toAdd_"+code).style.display = "none" }
9.進行添加測試,當點擊添加成功後,如不顯示添加按鈕表示成功
1.在index頁面添加股票成功後,隨後點擊進入我的中心center頁面,則顯示全部關注的股票信息,包括剛纔關注的股票
2.在我的中心頁面中,每支股票都有一個刪除按鈕,當用戶點擊刪除按鈕後則在此頁面中再也不顯示出該支股票,對應咋數據庫focus表中該支股票也直接被物理刪除
<script> $(document).ready(function(){ $("input[name='toDel']").each(function(){ var currentAdd = $(this); currentAdd.click(function(){ code = $(this).attr("systemIdVaule"); // alert("/del/" + code + ".html"); $.get("/del/" + code + ".html", function(data, status){ alert("數據: " + data + "\n狀態: " + status); window.location.reload() }); }); }); }); </script>
@route(r"/del/(\d+)\.html") def del_focus(page_num, ret): pass
# 1. 獲取添加按鈕觸發的ajax請求地址中的股票代碼 stock_code = ret.group(1) # print(stock_code) # 2.判斷獲取到的股票代碼是否存在 res = connect_db("select * from info where code = '%s'" % stock_code) if not res: return "非法請求<This stock does not exist>" # 3.判斷該股票是否已經關注,未關注表示非法刪除請求 res = connect_db("select * from info as i inner join focus as f on i.id = f.info_id where i.code = '%s'" % stock_code) if not res: return "該股票未關注...." # 4.取關股票,並修改info表中is_add字段爲0表示在頁面顯示添加按鈕 connect_db("delete from focus where info_id = (select id from info where code = '%s')" % stock_code) connect_db("update info set is_add = 0 where code = '%s'" % stock_code) return "取關股票成功"
3.進行測試
1.在templates模板目錄下建立update.html文件,代碼以下
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>首頁 - 我的選股系統 V5.87</title> <link href="/css/bootstrap.min.css" rel="stylesheet"> <script src="/js/jquery-1.12.4.min.js"></script> <script src="/js/bootstrap.min.js"></script> </head> <body> <div class="navbar navbar-inverse navbar-static-top "> <div class="container"> <div class="navbar-header"> <button class="navbar-toggle" data-toggle="collapse" data-target="#mymenu"> <span class="icon-bar"></span> <span class="icon-bar"></span> <span class="icon-bar"></span> </button> <a href="#" class="navbar-brand">選股系統</a> </div> <div class="collapse navbar-collapse" id="mymenu"> <ul class="nav navbar-nav"> <li><a href="/index.html">股票信息</a></li> <li><a href="/center.html">我的中心</a></li> </ul> </div> </div> </div> <div class="container"> <div class="container-fluid"> <div class="input-group"> <span class="input-group-addon">正在修改:</span> <span class="input-group-addon">{%code%}</span> <input id="note_info" type="text" class="form-control" aria-label="Amount (to the nearest dollar)" value="{%note_info%}"> <span id="update" class="input-group-addon" style="cursor: pointer">修改</span> </div> </div> </div> </body> </html>
2.在update.html文件中編寫以下js,當用戶點擊修改按鈕,首先當用戶在我的中心頁面對股票點擊修改時,向http://127.0.0.1:7979/update/300320.html地址發送請求進入到修改界面,而後在修改界面點擊修改時,向http://127.0.0.1:7979/update/000581/備註信息.html地址發送請求,獲取響應內容最後跳轉到我的中心網頁
<script> $(document).ready(function(){ $("#update").click(function(){ var item = $("#note_info").val(); // alert("/update/{%code%}/" + item + ".html"); $.get("/update/{%code%}/" + item + ".html", function(data, status){ alert("數據: " + data + "\n狀態: " + status); self.location='/center.html'; }); }); }); </script>
3.在框架文件中建立show_update_page視圖函數,用於顯示修改備註信息頁面
<a type="button" class="btn btn-default btn-xs" href="/update/%s.html"> <span aria-hidden="true">⇋</span> 修改 </a>
@route(r"/update/(\d+)\.html") def show_update_page(page_num, ret): """顯示修改界面""" # 1.讀取修改界面代碼 with open("./templates/update.html", encoding="utf-8") as f: content = f.read() # 2. 獲取要修改的股票代碼 stock_code = ret.group(1) # 3. 獲取該關注股票的備註信息 res = connect_db("select f.not_info from info as i inner join focus as f on i.id = f.info_id where i.code = '%s'" % stock_code) not_info = res[0][0] # print(not_info, "wwwwwwwwwwwww") # 4. 替換html中的空缺兩次依次替換 content = re.sub(r"\{%note_info%\}", not_info, content) content = re.sub(r"\{%code%\}", stock_code, content) return content
4.在框架文件中定義save_update_data視圖函數用於保存股票修改後的備註信息
@route(r"/update/(\d+)/(.*)\.html") def save_update_data(page_num, ret): """將用戶修改的備註信息保存到數據庫""" # 1. 獲取股票代碼以及備註信息 stock_code = ret.group(1) comment = ret.group(2) # 2. 因以前添加關注功能對股票信息進行了驗證,因此在我的中心頁面的已關注的股票信息爲合法信息,因此直接寫入數據庫便可 connect_db("update focus set not_info = '%s' where info_id = (select id from info where code = %s)" %(comment, stock_code)) return """修改備註信息成功"""
comment = urllib.parse.unquote(comment)
5.這個項目有不少須要優化以及不足的地方,全部的Web項目大同小異都是這個流程,代碼不重要,重要的是明白瀏覽器服務器以及程序框架之間數據是怎麼傳遞的