Python mini-web框架4:添加路由和MySQL功能
一、用装饰器完成路由功能
-
1.1、用装饰器完成路由功能1
import re def index(): with open("./templates/index.html") as f: content = f.read() my_stock_info = "测试一下,数据" content = re.sub(r"\{%content%\}",my_stock_info,content) return content def center(): with open("./templates/center.html") as f: content = f.read() my_stock_info = "这是从数据库查询出来的数据" content = re.sub(r"\{%content%\}",my_stock_info,content) return content URL_FUNC_DICT = { "/index.py":index, "/center.py":center } def application(evn,start_reponse): start_reponse('200 OK',[('Content-Type','text/html;charset=utf-8')]) file_name = evn['PATH_INFO'] func = URL_FUNC_DICT[file_name] return func()
提示:主要是
URL_FUNC_DICT
字典的引入,不用再像以前那样的判断file_name
是否存在了,如下file_name = evn['PATH_INFO'] func = URL_FUNC_DICT[file_name] return func()
取代了下面的段代码
if file_name == "/index.py": return index() elif file_name == "/center.py": return center() else: return "Hello world !"
缺点:URL_FUNC_DICT字典还需要手动配置,以及file_name不存在的时候会出现问题,下面我们看 2 的优化
-
1.2、用装饰器完成路由功能2
目的:去掉1.1中的代码URL_FUNC_DICT = { "/index.py": index, "/center.py": center }
优化方式,使用带参数的装饰器来实现
URL_FUNC_DICT
来自动添加元素,代码如下# 定义一个空子典 URL_FUNC_DICT = dict() def route(url): """ 带参数的装饰器来做路由 :param url: 请求的url :return: 返回一个装饰器 """ def set_func(func): # 往空子典里面添加元素 URL_FUNC_DICT[url] = func def call_func(*args, **kwargs): return func(*args, **kwargs) return call_func return set_func
完整的代码如下
import re # 定义一个空子典 URL_FUNC_DICT = dict() # 用来存放url路由映射 def route(url): """ 带参数的装饰器来做路由 :param url: 请求的url :return: 返回一个装饰器 """ def set_func(func): # 添加键值对,key是需要访问的url,value是当这个url需要访问的时候,需要调用的函数引用 URL_FUNC_DICT[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() my_stock_info = "测试一下,数据" content = re.sub(r"\{%content%\}", my_stock_info, content) return content @route("/center.py") def center(): with open("./templates/center.html") as f: content = f.read() my_stock_info = "这是从数据库查询出来的数据" content = re.sub(r"\{%content%\}", my_stock_info, content) return content def application(evn, start_reponse): start_reponse('200 OK', [('Content-Type', 'text/html;charset=utf-8')]) file_name = evn['PATH_INFO'] func = URL_FUNC_DICT[file_name] return func()
-
1.3、用装饰器完成路由功能3:解决 字典
URL_FUNC_DICT
里面不存在键值对的情况-
方式一:使用
key in dict
,也就是判断一个键在字典中是否在存在,如下jk_dict = {"a":1,"b":2} key = "a" if key in jk_dict: print("%s的value是"%key,jk_dict[key]) else: print("键%s在字典里面不存在"% key)
-
方式二:使用
try
jk_dict = {"a":1,"b":2} key = "c" try: print("%s的value是" % key, jk_dict[key]) except Exception as ret: print("异常信息是%s"%str(ret))
-
对比两种方式的选择哪一个更好
使用try
还是比较好的,因为它具有异常转发的功能,而方式一没有
-
-
1.4、简单的解释一下路由
route
- 路由route:路由的功能是数据的转发,上面使用到路由的功能是字典的映射
二、伪静态、静态和动态的区别
目前开发的网站其实真正意义上都是动态网站,只是URL上有些区别,一般URL分为静态URL、动态URL、伪静态URL,他们的区别是什么?
-
2.1、静态URL
静态URL类似域名/news/hh/login.html
我们一般称为真静态URL,每个网页有真实的物理路径,也就是真实存在服务器里的。- 优点是:网站打开速度快,因为它不用进行运算;另外网址结构比较友好,利于记忆。
- 缺点是:最大的缺点是如果是中大型网站,则产生的页面特别多,不好管理。至于有的开发者说占用硬盘空间大,我觉得这个可有忽略不计,占用不了多少空间的,况且目前硬盘空间都比较大。还有的开发者说会伤硬盘,这点也可以忽略不计。
- 一句话总结: 静态网站对SEO的影响:静态URL对SEO肯定有加分的影响,因为打开速度快,这个是本质。
-
2.2、动态URL
动态URL类似域名/NewsMore.asp?id=5 或者 域名/DaiKuan.php?id=17
,带有?号的URL,我们一般称为动态网址,每个URL只是一个逻辑地址,并不是真实物理存在服务器硬盘里的。- 优点是:适合中大型网站,修改页面很方便,因为是逻辑地址,所以占用硬盘空间要比纯静态网站小。
- 缺点是:因为要进行运算,所以打开速度稍慢,不过这个可有忽略不计,目前有服务器缓存技术可以解决速度问题。最大的缺点是URL结构稍稍复杂,不利于记忆。
- 一句话总结: 动态URL对SEO的影响:目前百度SE已经能够很好的理解动态URL,所以对SEO没有什么减分的影响(特别复杂的URL结构除外)。所以你无论选择动态还是静态其实都无所谓,看你选择的程序和需求了。
-
2.3、伪静态URL
伪静态URL类似域名/course/2.html
这个URL和真静态URL类似。他是通过伪静态规则把动态URL伪装成静态网址。也是逻辑地址,不存在物理地址。- 优点是:URL比较友好,利于记忆。非常适合大中型网站,是个折中方案。
- 缺点是:设置麻烦,服务器要支持重写规则,小企业网站或者玩不好的就不要折腾了。另外进行了伪静态网站访问速度并没有变快,因为实质上它会额外的进行运算解释,反正增加了服务器负担,速度反而变慢,不过现在的服务器都很强大,这种影响也可以忽略不计。还有可能会造成动态URL和静态URL都被搜索引擎收录,不过可以用robots禁止掉动态地址。
- 一句话总结:使用的时候和动态URL一样,但是伪静态对SEO没有什么减分影响。
三、mini_frame框架添加MySQL功能
-
3.1、进入mysql
mysql -u 用户名 -p密码
如:
mysql -u root -p456123love
-
3.2、创建数据库
stock_db
以及表和数据stock_db.sql文件-
<1>、创建数据库
stock_db
以及使用# 创建数据库 `stock_db ` create database stock_db charset=utf8; # 使用数据库 `stock_db ` use stock_db;
-
<2>、导入数据(在练习的时候需要这个文件的可以找我要)
source stock_db.sql;
提示:
stock_db.sql
是一个sql文件
,里面是一些表创建以及数据导入的代码,在执行上面的代码的是一定要在stock_db.sql
文件同一个路径 -
<3>、
focus
与info
的表结构如下
focus表结构mysql> desc focus;
info表结构mysql> desc info;
-
-
3.3、mysql数据库查询的正式使用,效果如下:
效果-
def index():
里面的代码如下def index(): with open("./templates/index.html") as f: content = f.read() # my_stock_info = "测试一下,数据" # 创建Connection连接 conn = connect(host='ironman.ren', port=3306, database='stock_db', user='账号名', password='密码', charset='utf8') # 获得Cursor对象 cursor = conn.cursor() cursor.execute("select * from info;") stock_infos = cursor.fetchall() cursor.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" systemidvalue="000007"> </td> </tr> """ html = "" for line_info in stock_infos: html += tr_template%(line_info[0],line_info[1],line_info[2],line_info[3],line_info[4],line_info[5],line_info[6],line_info[7]) content = re.sub(r"\{%content%\}", str(html), content) return content
-
`def center():`里面的效果与代码如下def center():
里面的效果与代码如下
def center(): with open("./templates/center.html") as f: content = f.read() # 创建Connection连接 conn = connect(host='ironman.ren', port=3306, database='stock_db', user='账号名', password='密码', charset='utf8') # 获得Cursor对象 cursor = conn.cursor() cursor.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_infos = cursor.fetchall() cursor.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/300268.html"> <span class="glyphicon glyphicon-star" aria-hidden="true"></span> 修改 </a> </td> <td> <input type="button" value="删除" id="toDel" name="toDel" systemidvalue="300268"> </td> </tr> """ html = "" for line_info in stock_infos: html += tr_template % (line_info[0], line_info[1], line_info[2], line_info[3], line_info[4], line_info[5], line_info[6]) content = re.sub(r"\{%content%\}", str(html), content) return content
-
上述两个代码最主要的理解查询数据后再拼接,返回一个content
-
补充:
- 面向切面:装饰器添加功能,让原本的框架去调用,不用管其他的,只需要写自己函数内的代码