一、路由
1、mini_frame中实现简单的路由功能
mini_frame.py
# coding=UTF-8 import re def index(): with open("./templates/index.html") as f: content = f.read() # 使用正则表达式替换源模版中的数据 from_mysql_data = "这里以后放的是从数据库中查询出来的数据" content = re.sub(r"\{%content%\}", from_mysql_data, content) return content def center(): with open("./templates/center.html") as f: return f.read() URL_FUN_DIC = { "/index.py":index, "/center.py":center } def application(env, start_response): start_response('200 OK', [('Content-Type','text/html;charset=utf-8')]) file_name = env['PATH_INFO'] """ if file_name == "/index.py": return index() elif file_name == "/center.py": return center() else: return "我爱你中国..." """ func = URL_FUN_DIC[file_name] return func()
2、使用装饰器完成mini_frame.py的路由功能
mini_frame.py
# coding=UTF-8 import re URL_FUN_DIC = dict() def route(url): def set_func(func): # 在执行装饰的过程中将参数添加到字典中 URL_FUN_DIC[url] = func def call_func(*args, **kwargs): return func(*args, **kwargs) return call_func return set_func @route("/index.py") def index(): with open("./templates/index.html") as f: content = f.read() # 使用正则表达式替换源模版中的数据 from_mysql_data = "这里以后放的是从数据库中查询出来的数据" content = re.sub(r"\{%content%\}", from_mysql_data, content) return content @route("/center.py") 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'] """ if file_name == "/index.py": return index() elif file_name == "/center.py": return center() else: return "我爱你中国..." """ try: return URL_FUN_DIC[file_name]() except Exception as e: return "您访问的页面 %s 不存在" % str(e) return func()
二、伪静态、静态和动态
1、静态URL
静态URL类似 域名/news/2012-5-18/110.html 我们一般称为真静态URL,每个网页有真实的物理路径,也就是真实存在服务器里的。
优点是:
网站打开速度快,因为它不用进行运算;另外网址结构比较友好,利于记忆。
缺点是:
最大的缺点是如果是中大型网站,则产生的页面特别多,不好管理。至于有的开发者说占用硬盘空间大,我觉得这个可有忽略不计,占用不了多少空间的,况且目前硬盘空间都比较大。还有的开发者说会伤硬盘,这点也可以忽略不计。
一句话总结:
静态网站对SEO的影响:静态URL对SEO肯定有加分的影响,因为打开速度快,这个是本质。
2、动态URL
动态URL类似 域名/NewsMore.asp?id=5 或者 域名/DaiKuan.php?id=17,带有?号的URL,我们一般称为动态网址,每个URL只是一个逻辑地址,并不是真实物理存在服务器硬盘里的。
优点是:
适合中大型网站,修改页面很方便,因为是逻辑地址,所以占用硬盘空间要比纯静态网站小。
缺点是:
因为要进行运算,所以打开速度稍慢,不过这个可有忽略不计,目前有服务器缓存技术可以解决速度问题。最大的缺点是URL结构稍稍复杂,不利于记忆。
一句话总结:
动态URL对SEO的影响:目前百度SE已经能够很好的理解动态URL,所以对SEO没有什么减分的影响(特别复杂的URL结构除外)。所以你无论选择动态还是静态其实都无所谓,看你选择的程序和需求了。
3、伪静态URL
伪静态URL类似 域名/course/74.html 这个URL和真静态URL类似。他是通过伪静态规则把动态URL伪装成静态网址。也是逻辑地址,不存在物理地址。
优点是:
URL比较友好,利于记忆。非常适合大中型网站,是个折中方案。
缺点是:
设置麻烦,服务器要支持重写规则,小企业网站或者玩不好的就不要折腾了。另外进行了伪静态网站访问速度并没有变快,因为实质上它会额外的进行运算解释,反正增加了服务器负担,速度反而变慢,不过现在的服务器都很强大,这种影响也可以忽略不计。还有可能会造成动态URL和静态URL都被搜索引擎收录,不过可以用robots禁止掉动态地址。
一句话总结:
对SEO的影响:和动态URL一样,对SEO没有什么减分影响。
4、让web服务器支持伪静态
(1)、修改web-server.py中捕获的请求后缀名
(2)、修改mini_frame.py框架
三、web服务器动态查询MySQL数据库中的数据并展示
1、准备数据库数据
create database stock_db charset=utf8; use stock_db; DROP TABLE IF EXISTS `focus`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `focus` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `note_info` varchar(200) DEFAULT '', `info_id` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`id`), KEY `info_id` (`info_id`), CONSTRAINT `focus_ibfk_1` FOREIGN KEY (`info_id`) REFERENCES `info` (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `focus` -- LOCK TABLES `focus` WRITE; /*!40000 ALTER TABLE `focus` DISABLE KEYS */; INSERT INTO `focus` VALUES (2,'你确定要买这个?',36),(3,'利好',37),(9,'',88),(10,'',89),(13,'',1); /*!40000 ALTER TABLE `focus` ENABLE KEYS */; UNLOCK TABLES; -- -- Table structure for table `info` -- DROP TABLE IF EXISTS `info`; /*!40101 SET @saved_cs_client = @@character_set_client */; /*!40101 SET character_set_client = utf8 */; CREATE TABLE `info` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `code` varchar(6) NOT NULL COMMENT '股票代码', `short` varchar(10) NOT NULL COMMENT '股票简称', `chg` varchar(10) NOT NULL COMMENT '涨跌幅', `turnover` varchar(255) NOT NULL COMMENT '换手率', `price` decimal(10,2) NOT NULL COMMENT '最新价', `highs` decimal(10,2) NOT NULL COMMENT '前期高点', `time` date DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=95 DEFAULT CHARSET=utf8; /*!40101 SET character_set_client = @saved_cs_client */; -- -- Dumping data for table `info` -- LOCK TABLES `info` WRITE; /*!40000 ALTER TABLE `info` DISABLE KEYS */; INSERT INTO `info` VALUES (1,'000007','全新好','10.01%','4.40%',16.05,14.60,'2017-07-18'),(2,'000036','华联控股','10.04%','10.80%',11.29,10.26,'2017-07-20'), (3,'000039','中集集团','1.35%','1.78%',18.07,18.06,'2017-06-28'),(4,'000050','深天马A','4.38%','4.65%',22.86,22.02,'2017-07-19'), (5,'000056','皇庭国际','0.39%','0.65%',12.96,12.91,'2017-07-20'),(6,'000059','华锦股份','3.37%','7.16%',12.26,12.24,'2017-04-11'), (7,'000060','中金岭南','1.34%','3.39%',12.08,11.92,'2017-07-20'),(8,'000426','兴业矿业','0.41%','2.17%',9.71,9.67,'2017-07-20'), (9,'000488','晨鸣纸业','6.30%','5.50%',16.37,15.59,'2017-07-10'),(10,'000528','柳工','1.84%','3.03%',9.42,9.33,'2017-07-19'), (11,'000540','中天金融','0.37%','5.46%',8.11,8.08,'2017-07-20'),(12,'000581','威孚高科','3.49%','3.72%',27.00,26.86,'2017-06-26'), (13,'000627','天茂集团','5.81%','12.51%',10.93,10.33,'2017-07-20'),(14,'000683','远兴能源','6.42%','21.27%',3.48,3.29,'2017-07-19'), (15,'000703','恒逸石化','0.24%','1.65%',16.92,16.88,'2017-07-20'),(16,'000822','山东海化','6.60%','8.54%',9.05,8.75,'2017-07-06'), (17,'000830','鲁西化工','1.38%','4.80%',7.36,7.26,'2017-07-20'),(18,'000878','云南铜业','1.26%','3.23%',14.50,14.47,'2017-07-19'), (19,'000905','厦门港务','5.44%','10.85%',15.90,15.60,'2017-04-20'),(20,'000990','诚志股份','0.53%','1.00%',16.99,16.90,'2017-07-20'), (21,'002019','亿帆医药','1.19%','2.81%',17.05,16.85,'2017-07-20'),(22,'002078','太阳纸业','2.05%','1.90%',8.45,8.29,'2017-07-19'), (23,'002092','中泰化学','7.25%','6.20%',15.53,14.48,'2017-07-20'),(24,'002145','中核钛白','2.43%','7.68%',6.75,6.61,'2017-07-19'), (25,'002285','世联行','8.59%','5.66%',9.23,8.50,'2017-07-20'),(26,'002311','海大集团','1.13%','0.24%',18.81,18.63,'2017-07-19'), (27,'002460','赣锋锂业','9.41%','9.00%',63.70,58.22,'2017-07-20'),(28,'002466','天齐锂业','3.62%','3.66%',68.44,66.05,'2017-07-20'), (29,'002470','金正大','2.30%','0.99%',8.00,7.82,'2017-07-20'),(30,'002496','辉丰股份','3.15%','4.29%',5.24,5.08,'2017-04-10'), (31,'002497','雅化集团','0.38%','12.36%',13.10,13.05,'2017-07-20'),(32,'002500','山西证券','0.44%','3.70%',11.49,11.44,'2017-07-20'), (33,'002636','金安国纪','2.70%','11.59%',19.80,19.42,'2017-07-19'),(34,'300032','金龙机电','0.66%','0.72%',15.28,15.18,'2017-07-20'), (35,'300115','长盈精密','0.60%','0.59%',33.50,33.41,'2017-07-19'),(36,'300268','万福生科','-10.00%','0.27%',31.77,13.57,'2017-04-10'), (37,'300280','南通锻压','3.31%','0.66%',32.20,32.00,'2017-04-11'),(38,'300320','海达股份','0.28%','0.82%',18.26,18.21,'2017-07-20'), (39,'300408','三环集团','1.69%','0.81%',23.42,23.17,'2017-07-19'),(40,'300477','合纵科技','2.84%','5.12%',22.10,22.00,'2017-07-12'), (41,'600020','中原高速','5.46%','4.48%',5.60,5.31,'2017-07-20'),(42,'600033','福建高速','1.01%','1.77%',4.00,3.99,'2017-06-26'), (43,'600066','宇通客车','4.15%','1.49%',23.08,23.05,'2017-06-13'),(44,'600067','冠城大通','0.40%','2.97%',7.56,7.53,'2017-07-20'), (45,'600110','诺德股份','2.08%','4.26%',16.16,15.83,'2017-07-20'),(46,'600133','东湖高新','9.65%','21.74%',13.64,12.44,'2017-07-20'), (47,'600153','建发股份','3.65%','2.03%',13.35,13.21,'2017-07-10'),(48,'600180','瑞茂通','2.20%','1.07%',14.86,14.54,'2017-07-20'), (49,'600183','生益科技','6.94%','4.06%',14.94,14.12,'2017-07-19'),(50,'600188','兖州煤业','1.53%','0.99%',14.56,14.43,'2017-07-19'), (51,'600191','华资实业','10.03%','11.72%',15.80,14.36,'2017-07-20'),(52,'600210','紫江企业','6.03%','10.90%',6.68,6.30,'2017-07-20'), (53,'600212','江泉实业','1.39%','1.78%',10.20,10.15,'2017-07-19'),(54,'600225','*ST松江','4.96%','2.47%',5.71,5.61,'2017-04-13'), (55,'600230','沧州大化','5.74%','13.54%',43.26,40.91,'2017-07-20'),(56,'600231','凌钢股份','2.79%','3.77%',3.68,3.60,'2017-07-19'), (57,'600291','西水股份','10.02%','9.23%',34.71,31.55,'2017-07-20'),(58,'600295','鄂尔多斯','4.96%','12.62%',16.51,15.73,'2017-07-20'), (59,'600303','曙光股份','8.37%','14.53%',11.53,10.64,'2017-07-20'),(60,'600308','华泰股份','1.12%','2.66%',6.30,6.26,'2017-07-19'), (61,'600309','万华化学','0.03%','1.78%',31.81,31.80,'2017-07-20'),(62,'600352','浙江龙盛','0.39%','1.85%',10.32,10.28,'2017-07-20'), (63,'600354','敦煌种业','7.89%','18.74%',9.44,8.75,'2017-07-20'),(64,'600408','安泰集团','1.98%','3.38%',4.13,4.12,'2017-04-13'), (65,'600409','三友化工','0.62%','3.78%',11.36,11.29,'2017-07-20'),(66,'600499','科达洁能','0.46%','3.94%',8.84,8.80,'2017-07-20'), (67,'600508','上海能源','3.26%','2.99%',13.32,13.01,'2017-07-19'),(68,'600563','法拉电子','0.32%','1.36%',53.67,53.50,'2017-07-20'), (69,'600567','山鹰纸业','0.76%','2.85%',3.98,3.96,'2017-07-19'),(70,'600585','海螺水泥','0.45%','0.61%',24.51,24.44,'2017-07-19'), (71,'600668','尖峰集团','4.35%','6.43%',18.70,18.36,'2017-04-13'),(72,'600688','上海石化','2.72%','0.91%',6.80,6.74,'2017-06-01'), (73,'600729','重庆百货','5.70%','3.34%',27.45,27.13,'2017-06-29'),(74,'600739','辽宁成大','3.30%','3.50%',19.74,19.11,'2017-07-20'), (75,'600779','水井坊','3.85%','2.77%',29.39,28.30,'2017-07-20'),(76,'600781','辅仁药业','8.61%','4.16%',23.46,21.89,'2017-05-02'), (77,'600801','华新水泥','4.00%','10.15%',12.99,12.49,'2017-07-20'),(78,'600846','同济科技','2.06%','17.41%',9.39,9.26,'2017-04-13'), (79,'600884','杉杉股份','1.08%','3.53%',20.67,20.45,'2017-07-20'),(80,'600966','博汇纸业','2.89%','5.54%',6.41,6.28,'2017-07-19'), (81,'600971','恒源煤电','2.36%','8.81%',12.16,11.88,'2017-07-20'),(82,'601012','隆基股份','0.76%','1.30%',19.93,19.78,'2017-07-20'), (83,'601100','恒立液压','4.78%','0.92%',19.31,18.97,'2017-07-13'),(84,'601101','昊华能源','4.03%','6.06%',11.10,10.80,'2017-07-19'), (85,'601216','君正集团','2.16%','2.26%',5.20,5.10,'2017-04-17'),(86,'601666','平煤股份','2.81%','6.14%',6.96,6.77,'2017-07-20'), (87,'601668','中国建筑','2.39%','1.42%',10.70,10.45,'2017-07-20'),(88,'601678','滨化股份','0.13%','2.47%',7.92,7.91,'2017-07-20'), (89,'601918','新集能源','1.23%','3.11%',4.93,4.92,'2017-07-19'),(90,'603167','渤海轮渡','2.77%','3.34%',11.87,11.61,'2017-04-13'), (91,'603369','今世缘','3.34%','2.13%',14.24,13.78,'2017-07-20'),(92,'603589','口子窖','3.99%','1.84%',39.37,39.04,'2017-06-26'), (93,'603799','华友钴业','2.38%','7.19%',67.46,65.89,'2017-07-20'),(94,'603993','洛阳钼业','2.94%','2.50%',7.36,7.16,'2017-07-19');
2、修改mini_frame.py内容
# coding=UTF-8 import re from pymysql import connect URL_FUN_DIC = dict() def route(url): def set_func(func): # 在执行装饰的过程中将参数添加到字典中 URL_FUN_DIC[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") as f: content = f.read() # 从数据库中将数据查询出来 conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8') # 获得cursor对象 cs = conn.cursor() cs.execute("select * from info;") stock_info_list = cs.fetchall() cs.close() conn.close() #按照页面要求的格式组装数据 tr_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> """ # 使用正则表达式替换源模版中的数据 from_mysql_data = "" for data in stock_info_list: from_mysql_data += tr_template %(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[1]) # 使用正则表达式替换源模版中的数据 # from_mysql_data = "这里以后放的是从数据库中查询出来的数据" content = re.sub(r"\{%content%\}", from_mysql_data, content) return content @route("/center.html") def center(): with open("./templates/center.html") as f: content = f.read() # 从数据库中将数据查询出来 conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8') # 获得cursor对象 cs = conn.cursor() cs.execute("select i.code,i.short,i.chg,i.turnover,i.price,i.highs,f.note_info from info as i inner join focus as f on i.id=f.info_id;") stock_info_list = cs.fetchall() cs.close() conn.close() #按照页面要求的格式组装数据 tr_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 class="glyphicon glyphicon-star" aria-hidden="true"></span> 修改 </a> </td> <td> <input type="button" value="删除" id="toDel" name="toDel" systemidvaule="%s"> </td> </tr> """ # 使用正则表达式替换源模版中的数据 from_mysql_data = "" for data in stock_info_list: from_mysql_data += tr_template %(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[0],data[0]) # 使用正则表达式替换源模版中的数据 # from_mysql_data = "这里以后放的是从数据库中查询出来的数据" content = re.sub(r"\{%content%\}", from_mysql_data, content) return content def application(env, start_response): start_response('200 OK', [('Content-Type','text/html;charset=utf-8')]) file_name = env['PATH_INFO'] """ if file_name == "/index.py": return index() elif file_name == "/center.py": return center() else: return "我爱你中国..." """ try: return URL_FUN_DIC[file_name]() except Exception as e: return "您访问的页面 %s 不存在" % str(e) return func()
四、mini_frame.py框架路由支持正则
1、修改mini_frame.py代码
@route(r"/add/\d+\.html") def add_func(): return "ADD 0K...." def application(env, start_response): start_response('200 OK', [('Content-Type','text/html;charset=utf-8')]) file_name = env['PATH_INFO'] """ if file_name == "/index.py": return index() elif file_name == "/center.py": return center() else: return "我爱你中国..." """ try: # return URL_FUN_DIC[file_name]() """ 使用正则表达式当作装饰器的参数之后,字典中的数据如下: { "/index.html":index, "/center.html"center, r"/add/\d+\.html":add_func } 使用item()方法进行遍历,取出每一个url和func """ for url, func in URL_FUN_DIC.items(): ret = re.match(url, file_name) if ret: return func() else: return "请求的页面 %s 不存在" % file_name except Exception as e: return "您访问的页面 %s 不存在" % str(e) return func()
2、实现添加关注功能
# coding=UTF-8 import re from pymysql import connect URL_FUN_DIC = dict() def route(url): def set_func(func): # 在执行装饰的过程中将参数添加到字典中 URL_FUN_DIC[url] = func def call_func(*args, **kwargs): return func(*args, **kwargs) return call_func return set_func @route("/index.html") def index(ret): with open("./templates/index.html") as f: content = f.read() # 从数据库中将数据查询出来 conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8') # 获得cursor对象 cs = conn.cursor() cs.execute("select * from info;") stock_info_list = cs.fetchall() cs.close() conn.close() #按照页面要求的格式组装数据 tr_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> """ # 使用正则表达式替换源模版中的数据 from_mysql_data = "" for data in stock_info_list: from_mysql_data += tr_template %(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[7],data[1]) # 使用正则表达式替换源模版中的数据 # from_mysql_data = "这里以后放的是从数据库中查询出来的数据" content = re.sub(r"\{%content%\}", from_mysql_data, content) return content @route("/center.html") def center(ret): with open("./templates/center.html") as f: content = f.read() # 从数据库中将数据查询出来 conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8') # 获得cursor对象 cs = conn.cursor() cs.execute("select i.code,i.short,i.chg,i.turnover,i.price,i.highs,f.note_info from info as i inner join focus as f on i.id=f.info_id;") stock_info_list = cs.fetchall() cs.close() conn.close() #按照页面要求的格式组装数据 tr_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 class="glyphicon glyphicon-star" aria-hidden="true"></span> 修改 </a> </td> <td> <input type="button" value="删除" id="toDel" name="toDel" systemidvaule="%s"> </td> </tr> """ # 使用正则表达式替换源模版中的数据 from_mysql_data = "" for data in stock_info_list: from_mysql_data += tr_template %(data[0],data[1],data[2],data[3],data[4],data[5],data[6],data[0],data[0]) # 使用正则表达式替换源模版中的数据 # from_mysql_data = "这里以后放的是从数据库中查询出来的数据" content = re.sub(r"\{%content%\}", from_mysql_data, content) return content @route(r"/add/(\d+)\.html") def add_func(ret): # 获取第一个分组(股票的code) stock_code = ret.group(1) # 判断当前股票是否存在 conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8') # 获取游标 cs = conn.cursor() sql = """select * from info where code = %s""" cs.execute(sql, (stock_code,)) # 如果没有当前代码,提示并return if not cs.fetchone(): cs.close() conn.close() return "没有这只股票,请重试" # 判断当前选中的股票是否已经关注过 sql = """select * from info as i inner join focus as f on i.id=f.info_id where i.code = %s""" cs.execute(sql, stock_code) # 如果已经关注了当前代码,提示并return if cs.fetchone(): cs.close() conn.close() return "您已经关注过这只股票,请勿重复关注" # 可以开始关注操作,添加关注 sql = """insert into focus(info_id) select id from info where code=%s""" cs.execute(sql, stock_code) conn.commit() cs.close() conn.close() return "关注 成功 .... " def application(env, start_response): start_response('200 OK', [('Content-Type','text/html;charset=utf-8')]) file_name = env['PATH_INFO'] """ if file_name == "/index.py": return index() elif file_name == "/center.py": return center() else: return "我爱你中国..." """ try: # return URL_FUN_DIC[file_name]() """ 使用正则表达式当作装饰器的参数之后,字典中的数据如下: { "/index.html":index, "/center.html"center, r"/add/\d+\.html":add_func } 使用item()方法进行遍历,取出每一个url和func """ for url, func in URL_FUN_DIC.items(): ret = re.match(url, file_name) if ret: return func(ret) else: return "请求的页面 %s 不存在" % file_name except Exception as e: return "您访问的页面 %s 不存在" % str(e) return func()
3、实现取消关注的功能
@route(r"/del/(\d+)\.html") def add_func(ret): # 获取第一个分组(股票的code) stock_code = ret.group(1) # 判断当前股票是否存在 conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8') # 获取游标 cs = conn.cursor() sql = """select * from info where code = %s""" cs.execute(sql, (stock_code,)) # 如果没有当前代码,提示并return if not cs.fetchone(): cs.close() conn.close() return "没有这只股票,请重试" # 判断当前选中的股票是否已经关注过 sql = """select * from info as i inner join focus as f on i.id=f.info_id where i.code = %s""" cs.execute(sql, stock_code) # 如果没有关注当前代码,提示并return if not cs.fetchone(): cs.close() conn.close() return "您没有关注过这只股票,取消失败" # 可以开始取消关注操作,删除关注 sql = """delete from focus where info_id = (select id from info where code=%s)""" cs.execute(sql, stock_code) conn.commit() cs.close() conn.close() return "取消关注 成功 .... "
4、实现更新股票备注信息的功能
@route(r"/update/(\d+)\.html") def to_update_view(ret): """跳转到修改数据的页面""" # 获取股票code stock_code = ret.group(1) # 打开模版页面 with open("./templates/update.html") as f: content = f.read() # 根据股票代码查询相关数据 conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8') cs = conn.cursor() sql = """select f.note_info from focus as f inner join info as i on i.id=f.info_id where i.code=%s;""" cs.execute(sql, stock_code) stock_infos = cs.fetchone() note_info = stock_infos[0] # 获取当前股票的备注信息,用于页面回显 cs.close() conn.close() # 替换html页面中的数据 content = re.sub(r"\{%note_info%\}", note_info, content) content = re.sub(r"\{%code%\}", stock_code, content) return content @route(r"/update/(\d+)/(.*)\.html") def update_stock(ret): """修改股票信息""" stock_code = ret.group(1) comment = ret.group(2) conn = connect(host='localhost', port=3306, user='root', password='mysql', database='stock_db', charset='utf8') cs = conn.cursor() sql = """update focus set note_info=%s where info_id = (select id from info where code = %s)""" cs.execute(sql, (comment, stock_code)) conn.commit() cs.close() conn.close() return "修改成功..."
5、url中有输入非字母时的URL解码
(1)、抛出问题
当修改的备注信息中有特殊字符或者中文的时候,出现一下情况
解决方案:使用python中的 urllib.parse 模块进行编、解码
(2)、导入urllib.parse模块
import urllib.parse
(3)、修改保存备注信息的方法
# 数据使用URL编码 urllib.parse,quote(字符串) # 将URL编码方式的字符串进行解码 urllib.parse.unquote(url编码方式的字符串)
五、Log日志
1、日志级别
日志一共分成5个等级,从低到高分别是:DEBUG INFO WARNING ERROR CRITICAL
说明:
DEBUG:详细的信息,通常只出现在诊断问题上
INFO:确认一切按预期运行
WARNING:一个迹象表明,一些意想不到的事情发生了,或表明一些问题在不久的将来(例如。磁盘空间低”)。这个软件还能按预期工作。
ERROR:更严重的问题,软件没能执行一些功能
CRITICAL:一个严重的错误,这表明程序本身可能无法继续运行
这5个等级,也分别对应5种打日志的方法: debug 、info 、warning 、error 、critical。默认的是WARNING,当在WARNING或之上时才被跟踪。
2、日志输出
有两种方式记录跟踪,一种输出控制台,另一种是记录到文件中,如日志文件。
(1)、将日志输出到控制台
# 导入log日志模块 import logging """ 设置默认日志等级,格式化要输出的内容 """ logging.basicConfig(level=logging.WARNING, format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s') # 开始使用log功能 logging.info('这是 loggging info message') logging.debug('这是 loggging debug message') logging.warning('这是 loggging a warning message') logging.error('这是 an loggging error message') logging.critical('这是 loggging critical message') """ 输出结果: 2018-03-25 19:51:38,525 - 模拟京东查询.py[line:9] - WARNING: 这是 loggging a warning message 2018-03-25 19:51:38,526 - 模拟京东查询.py[line:10] - ERROR: 这是 an loggging error message 2018-03-25 19:51:38,527 - 模拟京东查询.py[line:11] - CRITICAL: 这是 loggging critical message 只有是WARNING以上的日志等级才会输出,因为设置了默认等级为 WARNING """
说明:
通过logging.basicConfig函数对日志的输出格式及方式做相关配置,上面代码设置日志的输出等级是WARNING级别,意思是WARNING级别以上的日志才会输出。另外还制定了日志输出的格式。
注意,只要用过一次log功能再次设置格式时将失效,实际开发中格式肯定不会经常变化,所以刚开始时需要设定好格式。
(2)、将日志输出到日志文件
将日志输出到文件,只需要在logging.basicConfig函数中设置好输出文件的文件名和写文件的模式。
import logging logging.basicConfig(level=logging.WARNING, filename='./log.txt', # 设置文件的名称以及位置 filemode='w', # 设置打开日志文件的方式 format='%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s') # use logging logging.info('这是 loggging info message') logging.debug('这是 loggging debug message') logging.warning('这是 loggging a warning message') logging.error('这是 an loggging error message') logging.critical('这是 loggging critical message')
(3)、将日志输出到控制台和日志文件
import logging # 第一步,创建一个logger logger = logging.getLogger() logger.setLevel(logging.INFO) # 设置日志的等级等级总开关 # 第二步,创建一个handler对象,用于写入日志文件 logfile = './log.txt' fh = logging.FileHandler(logfile, mode='a') # open的打开模式这里可以进行参考 fh.setLevel(logging.DEBUG) # 输出到file的log等级的开关 # 第三步,再创建一个handler,用于输出到控制台 ch = logging.StreamHandler() ch.setLevel(logging.WARNING) # 输出到console的log等级的开关 # 第四步,定义日志信息的输出格式 formatter = logging.Formatter("%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s") fh.setFormatter(formatter) # 给文件中的日志信息设置输出格式 ch.setFormatter(formatter) # 给控制台的日志信息设置输出格式 # 第五步,将logger添加到handler里面 logger.addHandler(fh) logger.addHandler(ch) # 日志 logger.debug('这是 logger debug message') logger.info('这是 logger info message') logger.warning('这是 logger warning message') logger.error('这是 logger error message') logger.critical('这是 logger critical message')
3、日志格式说明
logging.basicConfig函数中,可以指定日志的输出格式format,这个参数可以输出很多有用的信息,如下:
%(levelno)s: 打印日志级别的数值
%(levelname)s: 打印日志级别名称
%(pathname)s: 打印当前执行程序的路径,其实就是sys.argv[0]
%(filename)s: 打印当前执行程序名
%(funcName)s: 打印日志的当前函数
%(lineno)d: 打印日志的当前行号
%(asctime)s: 打印日志的时间
%(thread)d: 打印线程ID
%(threadName)s: 打印线程名称
%(process)d: 打印进程ID
%(message)s: 打印日志信息