时间:2023-06-11 13:09:01 | 来源:网站运营
时间:2023-06-11 13:09:01 来源:网站运营
用40行代码写python网页模版渲染引擎:引子#!/usr/bin/python# -*- coding: UTF-8 -*-print "Content-type:text/html"print # 空行,告诉服务器结束头部print '<html>'print '<head>'print '<meta charset="utf-8">'print '<title>Hello World - 我的第一个 CGI 程序!</title>'print '</head>'print '<body>'print '<h2>Hello World! 我是来自菜鸟教程的第一CGI程序</h2>'print '</body>'print '</html>'
看着就觉得很丑陋是不是,这也就讲解下原理而已,真要实际做网页,估计要累死半头牛,绝对不能实战的。俗话说,上帝的归上帝,凯撒的归凯撒,所以我们要把模版/html和业务逻辑/python分离开来,这样势必需要一套模版引擎,能把数据嵌套/替换到模版上去。 在这里罗布大神第一个想到的就是有木有现成的模版引擎可以用,我找呀找,dingo,flask我去太复杂了,有些人觉得容易,你觉得容易你去用呀,话说你给这些框架添加过一行代码么?这些框架作者是你大爷?你咋这么向着他们,说话要客观呀。反正我觉得是太难了。后来找到一个mustache的python版本,pystache。mustache是一个非常舒服的客户端/js模版引擎,我以前用起来很爽的,建议做前端的同学们可以了解下,但是在python下,各种出错,我要疯了,麻烦作者稍微用点心吧,遂放弃,算了算了,自己撸起袖子来写个模版引擎,话说我也是自称大神的人。国内自己写模版引擎或者自己写一门语言解析器的人不多吧,我弱弱的问一下。>>>"{} {}".format("hello", "world") # 不设置指定位置,按默认顺序'hello world'>>> "{0} {1}".format("hello", "world") # 设置指定位置'hello world'>>> "{1} {0} {1}".format("hello", "world") # 设置指定位置'world hello world'#!/usr/bin/python# -*- coding: UTF-8 -*-print("网站名:{name}, 地址 {url}".format(name="菜鸟教程", url="www.runoob.com"))# 通过字典设置参数site = {"name": "菜鸟教程", "url": "www.runoob.com"}print("网站名:{name}, 地址 {url}".format(**site))# 通过列表索引设置参数my_list = ['菜鸟教程', 'www.runoob.com']print("网站名:{0[0]}, 地址 {0[1]}".format(my_list)) # "0" 是必须的
怎么样?看了这几个列子,看的我热血冲动,差点就扑上去,已经很接近模版渲染引擎了 那么我们来写模版吧:模版1 mb.html长这样,是不是很清爽呀<!DOCTYPE html><html><head><meta charset="utf-8"><title>菜鸟教程(runoob.com)</title></head><body> <h1>我的第一个标题</h1> <p>网站名:{name}, 地址 {url}</p></body></html>
程序怎么写呢?```#!/usr/bin/python# -*- coding: UTF-8 -*-#引入操作系统库import os,sys#输出页面文件头部print ("Content-type:text/html/n/n")#定义要传给模版的数据site = {"name": "菜鸟教程", "url": "www.runoob.com"}#打开模版文件并读取内容file="mb.html"if os.path.exists(file) : f=open(file) str=f.read() f.close() #渲染:数据传递给模版 str=str.format(**site) #输出给客户端 print(str)
好了,亲们,注释写的清清楚楚,我们要用python自带的字符串库format就完成了模版的数据传递/渲染工作,但是不要高兴的太早,format虽然好用,还差点意思,别人家的模版可以支持一般的循环渲染、条件渲染的。比如我要把list1 = ['physics', 'chemistry', 1997, 2000]这样的一个数组,甚至把一个表格list2 = [['physics', 'zhangsan', 1998, 2001], ['math', '', lisi, 2000] ['physics', 'wangwu', 1999, 2003]]渲染
这样的渲染要累死人的吧 渲染list模版要写成,str="{0[0]}, {0[1]}, {0[2]}, {0[3]}"
然后用 str.format(list1)来渲染,list2的模版已经复杂的我不想写了,并且有时候你根本不知道list2里边到底有几组数据,这时候模版根本没办法写,所以模版要支持一定的逻辑才好,为此,我们需要写一个更牛的format,也就是我标题写的自己写个模版引擎啦,蛤~,原来你说的模版引擎就是format,没错,嗯,不过要深加工下format,format做模版引擎还差点意思的,让我们来定义个函数,扩展format,就叫supformat吧,顾名思义,就是超级format 引入 {for 变量} 内容 {/for} 来执行循环和条件,如果变量为列表 内容会被列表的每个元素重复渲染,如果变量不存在,内容不会被渲染,如果变量不是列表 但存在,变量会被正常渲染,看说明应当一点都不绕口吧,蛤~#!/usr/bin/python# -*- coding: UTF-8 -*-#str:模版字符串 list1:传入的数据,可以是字典、列表、对象def supformat(str,list1): pos=str.find("{for ") if pos>=0: # print(pos) posend=str.find("{/for}",pos) if posend<0: print("need a {/for}") return ""; prestr=str[0:pos] endstr=str[posend+6:] keypos=str.find("}",pos) listkey=str[pos+5:keypos] str=str[keypos+1:posend] #print listkey,str if list1.has_key(listkey) : #如果变量不存在,内容不会被选择 mlist=list1[listkey] if type(mlist)==list : #如果变量存在 会被渲染 c=len(mlist) tmp="" for i in xrange(c): tmp+=supformat(str,mlist[i])#str.format(mlist[i]) # print str, mlist[i] str=tmp elif mlist: #判断true or false #如果变量不是列表 但存在,变量会被正常渲染 str=supformat(str,mlist)#str.format(list['listkey']) else: #如果变量为0或者false 不会被渲染 str="" else: #如果变量不存在,内容不会被渲染 str="" str=supformat(prestr,list1)+str+supformat(endstr,list1) #支持递归渲染 else: # 检查是否字典 if type(list1)==dict : str=str.format(**list1) #字典渲染方式 else : str=str.format(list1) #非字典渲染方式 return str
这个模版引擎写好了,怎么样,是不是没有想想的那么复杂,老祖宗说的好“天下事有难易乎?为则难者亦易矣”,非常鼓励我们自己的程序员写自己的模版引擎,写自己的框架,发明自己的计算机语言,整天你们叫嚷着别人写的这个框架好,别人发明的那个好,跟你你什么关系,自己写的也就算了,为别人写的东西你们互相奚落,还发明了鄙视链,害不害臊呀? 好了,我们言归正传,看看这个函数怎么用,假设我们把这个函数保存在一个supformat.py的文件里,那么使用的时候,要保证这个文件在当前目录或者sys.path的目录列表里,然后就引入就可以使用了,#!/usr/bin/python# -*- coding: UTF-8 -*-#引入操作系统库import os,sysimport supformat as sp #引入supformat函数#输出页面文件头部print ("Content-type:text/html/n/n")#定义要传给模版的数据list2 = [['physics', 'zhangsan', 1998, 2001], ['math', '', lisi, 2000] ['physics', 'wangwu', 1999, 2003]]site={"list2":list2}#打开模版文件并读取内容file="mb.html"if os.path.exists(file) : f=open(file) str=f.read() f.close() #渲染:数据传递给模版 str=supformat(site) # **划重点 模版渲染使用方法** #输出给客户端 print(str)
模版如下{for list2} {} {} {} {}{/for}
怎么样,模版是不是很清爽,另外要说下 模版里边需要用大括号的地方要用双大括号转义 样式表和js的大括号要写成 {{}}关键词:渲染,引擎