浏览 8744 次
锁定老帖子 主题:分享一个简单的python模板引擎
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2010-03-12
最后修改:2010-03-12
#coding:utf-8 __author__="sdm" __author_email='sdmzhu3@gmail.com' __date__ ="$2009-8-25 21:04:13$" ''' pytpl 类似php的模板类 ''' import sys import StringIO import os.path import os #模板的缓存 _tpl_cache={} class Pytpl: def __init__(self,tpl_path='./'): self.tpl_path=tpl_path self.data={} self.output = StringIO.StringIO() pass def set(self,name,value): ''' 设置模板变量 ''' self.data[name]=value; pass def get(self,name): ''' 得到模板变量 ''' t={} return t.get(name,'') pass def tpl(self,tplname): ''' 渲染模板 ''' f=self.tpl_path+tplname if not os.path.exists(f): raise Exception('tpl:[%s] is not exists' % f) mtime=os.stat(f).st_mtime if not _tpl_cache.has_key(f) or _tpl_cache[f]['time']<mtime: src_code=self.__compile__(open(f).read()) try: t=open(f+'.py','w') t.write(src_code) t.close() except: pass py_code=compile(src_code, f+'.py','exec') _tpl_cache[f]={'code':py_code,'time':mtime} else: py_code= _tpl_cache[f]['code'] exec(py_code, {'self':self}, self.data) return self.output.getvalue() def execute(self,code,data,tplname): ''' 执行这个模板 ''' py_file_name=tplname+'.py' f=open(py_file_name,'w') f.write(code) f.close() execfile(py_file_name, {'self':self}, data) def __compile__ (self,code): ''' 编译模板 查找 <?标记 ''' tlen=len(code); flag_start='<?' flag_end='?>' #默认普通标记 status=0 i=0 #分块标记 pos_end=0 pos_start=0 #缩进 global indent indent=0 py_code=[] def place_t_code(c,t_indent): ''' 基本的代码处理 ''' global indent if(c[0]=='='): return (' ' *4*indent) + 'echo ( \'%s\' % ('+c[1:]+'))' lines=c.split("\n") t=[] for i in lines: indent2=indent tmp=i.strip(" \n\r") c=tmp[len(tmp)-1:len(tmp)] #判定最后一个字符 if(c=='{'): indent+=1 tmp=tmp[0:len(tmp)-1]+":" elif(c=='}'): indent-=1 tmp=tmp[0:len(tmp)-1] t.append((' ' *4*indent2) +tmp ) return "\n".join(t) while 1: if i>=tlen:break c=code[i]; if status==0: #编译加速 pos_start=code.find(flag_start,pos_end); if(pos_start>-1): s=code[pos_end:pos_start] t_code= 'echo ( '+repr(s)+')' t_code=' '*indent*4 +t_code if s: py_code.append(t_code) i=pos_start last_pos=i #进入代码状态 status=1 continue else: #没有没有找到 pos_start=tlen t_code='echo ( '+repr(code[pos_end:pos_start])+' ) ' t_code=' '*indent*4 +t_code py_code.append(t_code) break if status==1: #查找结束标记 pos_end=code.find(flag_end,i) if(pos_end>-1): #需要跳过<? 这个标记 t_code=place_t_code(code[pos_start+2:pos_end],indent) #跳过?>结束标记 pos_end+=2 py_code.append(t_code) else: #没查找到直接结束 pos_end=tlen #需要跳过<? 这个标记 t_code=place_t_code(code[pos_start+2:pos_end],indent) py_code.append(t_code) break status=0 i=pos_end pass i+=1 py_code_str="#coding:utf-8\nimport sys;global echo;echo=self.output.write\n" py_code_str+="\n".join(py_code) py_code_str=py_code_str.replace("\t", " ") return py_code_str def test(): tpl=Pytpl('./'); tpl.set('title', '标题3') print tpl.tpl('test.html') pass if __name__ == "__main__": test() test.py import pytpl tpl=pytpl.Pytpl('./') tpl.set('title', 'test title') print tpl.tpl('test.html') 执行结果 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title>test title</title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> small3 11 </body> </html> 模板test.html <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> <html> <head> <title><?=title?></title> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> </head> <body> <? def add(a,b){ if(a+b<10){ echo('small'); } return a+b; } echo(add(1,2)); echo("\n"); echo(add(10,1)); ?> </body> </html> --- 编译的中间模板 #coding:utf-8 import sys;global echo;echo=self.output.write echo ( '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">\n<html>\n <head>\n <title>') echo ( '%s' % (title)) echo ( '</title>\n <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">\n </head>\n <body>\n\n') def add(a,b): if(a+b<10): echo('small'); return a+b; echo(add(1,2)); echo("\n"); echo(add(10,1)); echo ( '\n \n </body>\n</html>\n\n' ) 项目已经加入 googlecode http://code.google.com/p/pythontpl/ 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2010-03-14
增加了 include 功能
在模板中包含代码直接写 即可 <? include('head.html')?> tpl.set 的数据都是继承的 |
|
返回顶楼 | |