游戏电视苹果数码历史美丽
投稿投诉
美丽时装
彩妆资讯
历史明星
乐活安卓
数码常识
驾车健康
苹果问答
网络发型
电视车载
室内电影
游戏科学
音乐整形

Python大神教你300行代码搞定HTML模板渲染附源码

  一、前言
  模板语言由HTML代码和逻辑控制代码组成,此处PHP。通过模板语言可以快速的生成预想的HTML页面。应该算是后端渲染不可缺少的组成部分。二、功能介绍
  通过使用学习tornado、bottle的模板语言,我也效仿着实现可以独立使用的模板渲染的代码模块,模板语法来自tornado和bottle的语法。可以用来做一些简单的事情网页渲染,邮件内容生成等HTML显示方面。以下就是简单的语法使用介绍。
  1。变量。使用{{}}包裹起来,里面的变量为Python传入。模板渲染时会将传入的变量转换成字符串并填入对应位置。模板文件内容title{{mytitle}}titlelabel{{session。name}}labelpy代码调用thtml为上面的内容Template(thtml)。render(mytitle标题,sessionsomeobj)
  2。转义。默认传入的数据都会进行HTML转义,可以使用{rawvalue}来将value的内容按原始字符串输出。模板文件内容p{rawvalue}Py调用内容Template(thtml)。render(mytitlelabel显示标签label)
  3。条件控制。支持Python的if,elif,else。条件代码需要放在{}内部,并且在条件结束后需要额外增加{end},用于标识条件控制语句块范围。模板文件内容{ifa1}labelA大于1label{else}labelA小于或等于1label{end}py调用Template(thtml)。render(a1)
  4。循环控制。支持Python的for和while。与条件控制一样也需要放在{}内部,并且结束处需要额外增加{end},用于标识循环控制语句块的范围。模板文件内容{foriinrange(10)}label当前序号:{{i1}}label{end}py调用Template(thtml)。render()
  5。变量声明。如果需要在模板文件内声明一个变量,方便使用时,可以通过set来实现。具体格式为{setvxx}。通过set声明的变量在整个模板文件中都可以使用,包括在条件控制和循环控制中作为条件判断也可以。模板文件内容{seta1}labela的值:{{a}}label三、源码
  这个模板语言模块是在Python2。7上面开发使用的,如果要在Python3上使用需要对str和bytes进行一些处理即可,由于没有引用任何其他模块,可以很好地独立使用。1coding:utf823模板语言45TOKEN相关的定义6TOKENSBRACE{7TOKENSBLOCK8TOKENEXPRESSIONL{{9TOKENEXPRESSIONR}}10TOKENBLOCKL{11TOKENBLOCKR}12TOKENKEYSETset13TOKENKEYRAWraw14TOKENKEYIFif15TOKENKEYELIFelif16TOKENKEYELSEelse17TOKENKEYFORfor18TOKENKEYWHILEwhile19TOKENKEYENDend20TOKENKEYBREAKbreak21TOKENKEYCONTINUEcontinue22TOKENSPACE23TOKENCOLON:24Token标记{{}}{}25TOKENFLAGSET{TOKENSBRACE,TOKENSBLOCK}26简单的语句27TOKENKEYSETSIMPLEEXPRESSION{TOKENKEYSET,TOKENKEYRAW}28前置条件29TOKENKEYPRECONDITION{30end必须在ifelifelseforwhile后面31TOKENKEYEND:{TOKENKEYIF,TOKENKEYELIF,TOKENKEYELSE,32TOKENKEYFOR,TOKENKEYWHILE},33elif必须在if后面34TOKENKEYELIF:{TOKENKEYIF},35else必须在ifelif后面36TOKENKEYELSE:{TOKENKEYIF,TOKENKEYELIF,TOKENKEYFOR,TOKENKEYWHILE},37}38循环语句39TOKENKEYLOOP{TOKENKEYWHILE,TOKENKEYFOR}40循环的控制breakcontinue41TOKENKEYLOOPCTRL{TOKENKEYBREAK,TOKENKEYCONTINUE}4243classParseException(Exception):44pass4546classTemplateCode(object):47definit(self):48self。codeTrees{parent:None,nodes:〔〕}49self。cursorself。codeTrees50self。compiledcodeNone5152defcreatecode(self):53创建一个代码子块54childcodes{parent:self。cursor,nodes:〔〕}55self。cursor〔nodes〕。append(childcodes)56self。cursorchildcodes5758defclosecode(self):59关闭一个代码子块60assertself。cursor〔parent〕isnotNone,overflow61self。cursorself。cursor〔parent〕6263defappendtext(self,text):64添加文本65排除空行66self。cursor〔nodes〕。append(add(r)text)6768defappendexpress(self,express,rawFalse):69表达式70ifraw:71tempexptexpstr(s)express72else:73tempexptexpesc(s)express74self。cursor〔nodes〕。append(tempexp)75self。cursor〔nodes〕。append(add(texp))7677defappendstatement(self,statement):78语句79tempstatementsstatement80self。cursor〔nodes〕。append(tempstatement)8182defreset(self):83self。codeTrees{parent:None,nodes:〔〕}84self。cursorself。codeTrees85self。compiledcodeNone8687defbuildcode(self,filename):88tempcodebuff〔〕89self。writebuffwithindent(tempcodebuff,deftemplaterender():,0)90self。writebuffwithindent(tempcodebuff,codes〔〕,4)91self。writebuffwithindent(tempcodebuff,addcodes。append,4)92self。writecodes(tempcodebuff,self。codeTrees,4)93self。writebuffwithindent(tempcodebuff,return。join(codes),4)94tempcode。join(tempcodebuff)95self。compiledcodecompile(tempcode,filename,exec,dontinheritTrue)9697defwritecodes(self,codebuff,codes,indent):98fornodeincodes。get(nodes,〔〕):99ifisinstance(node,dict):100self。writecodes(codebuff,node,indent4)101else:102self。writebuffwithindent(codebuff,node,indent)103104defgenerate(self,kwargs):105tempnamespace{}106tempnamespace〔str〕self。toutf8107tempnamespace〔esc〕self。tosafeutf8108tempnamespace。update(kwargs)109exec(self。compiledcode,tempnamespace)110returntempnamespace〔templaterender〕()111112staticmethod113defwritebuffwithindent(codebuff,rawstr,indent):114115temp(indent)rawstr116codebuff。append(temp)117118staticmethod119deftoutf8(rawstr):120转换121ifisinstance(rawstr,str):122returnrawstr123elifisinstance(rawstr,bytes):124returnrawstr。decode()125returnstr(rawstr)126127staticmethod128deftosafeutf8(rawstr):129过滤html转义130textTemplateCode。toutf8(rawstr)131returntext。replace(,)。replace(,)。replace(,)132classTemplate(object):133模板类134definit(self,inputobj,filenamestring,namespace):135模板初始化136self。namespace{}137self。namespace。update(namespace)138将数据丢进去解析生成编译代码139self。lexerTemplateLexer(inputobj,filename)140141defrender(self,kwargs):142渲染模板143tempnamespace{}144tempnamespace。update(self。namespace)145tempnamespace。update(kwargs)146执行渲染147returnself。lexer。render(kwargs)148149classTemplateLexer(object):150模板语法分析器151definit(self,inputobb,filenamestring):152ifhasattr(inputobb,read):153self。rawstringinputobb。read()154else:155self。rawstringinputobb156self。filenamefilename157记录当前的位置158self。pos0159记录原始数据的总长度160self。rawstrlenlen(self。rawstring)161记录解析的数据162self。codedataTemplateCode()163开始解析164self。parsetemplate()165166defmatch(self,keyword,posNone):167returnself。rawstring。find(keyword,posifposisnotNoneelseself。pos)168169defcut(self,size1):170剪取数据size切割数据的大小,1表示全部171ifsize1:172newposself。rawstrlen173else:174newposself。possize175sself。rawstring〔self。pos:newpos〕176self。posnewpos177returns178179defremaining(self):180获取剩余大小181returnself。rawstrlenself。pos182183deffunctionbrace(self):184获取{{{185skipindexself。pos186whileTrue:187indexself。match(TOKENSBRACE,skipindex){{{188没找到189ifindex1:190returnNone,1191末尾192ifindexself。rawstrlen:193returnNone,1194匹配类型195nextvalueself。rawstring〔index1:index2〕196ifnextvaluenotinTOKENFLAGSET:197skipindexindex1198说明不是关键类型199continue200braceself。rawstring〔index:index2〕201returnbrace,index202returnNone,1203204defreadcontentwithtoken(self,index,begintoken,endtoken):205206读取匹配token的内容207208endindexself。match(endtoken)209ifendindex1:210returnParseException({0}missingendtoken{1}。format(begintoken,endtoken))211过滤begintoken212self。posindexlen(begintoken)213contentself。cut(endindexself。pos)214去除末尾endtoken215self。cut(len(endtoken))216returncontent217218defaddsimpleblockstatement(self,operator,suffix):219ifnotsuffix:220raiseParseException({0}missingcontent。format(operator))221ifoperatorTOKENKEYSET:222self。codedata。appendstatement(suffix)223elifoperatorTOKENKEYRAW:224self。codedata。appendexpress(suffix,True)225else:226raiseParseException({0}isundefined。format(operator))227228defparsetemplate(self):229解析模板230TODO检查模板文件是否更改过,如果没有则不需要重新解析231self。codedata。reset()232解析模板原文件233self。parse()234生成编译code235self。compiledcode()236237defrender(self,kwargs):238returnself。codedata。generate(kwargs)239240defparse(self,controloperatorNone,inloopFalse):241开始解析242whileTrue:243ifself。remaining()0:244ifcontroloperatororinloop:245raiseParseException(smissing{end}controloperator)246break247读取{{{248brace,indexself。functionbrace()249说明没有找到250ifnotbrace:251textself。cut(index)252self。codedata。appendtext(text)253continue254else:255textself。cut(indexself。pos)256iftext:257self。codedata。appendtext(text)258259ifbraceTOKENEXPRESSIONL:260contentself。readcontentwithtoken(index,TOKENEXPRESSIONL,TOKENEXPRESSIONR)。strip()261ifnotcontent:262raiseParseException(EmptyExpress)263self。codedata。appendexpress(content)264continue265elifbraceTOKENBLOCKL:266contentself。readcontentwithtoken(index,TOKENBLOCKL,TOKENBLOCKR)。strip()267ifnotcontent:268raiseParseException(Emptyblock)269270得到表达式forxinx;ifx;elifx;else;end;set;whilex;271operator,,suffixcontent。partition(TOKENSPACE)272ifnotoperator:273raiseParseException(blockmissingoperator)274275suffixsuffix。strip()276简单语句,setraw277ifoperatorinTOKENKEYSETSIMPLEEXPRESSION:278self。addsimpleblockstatement(operator,suffix)279elifoperatorinTOKENKEYLOOPCTRL:280ifnotinloop:281raiseParseException({0}mustinloopblock。format(operator))282self。codedata。appendstatement(operator)283else:284控制语句检查匹配if后面可以跟elifelse285preconditionTOKENKEYPRECONDITION。get(operator,None)286ifprecondition:287里面就是elifelseend288ifcontroloperatornotinprecondition:289raiseParseException({0}mustbehindwith{1}。format(operator,precondition))290elifoperatorTOKENKEYEND:291遇到{end}则结束292self。codedata。closecode()293return294else:295由于是依据if进入来计算elif,因此elif与if是同级的296self。codedata。closecode()297self。codedata。appendstatement(contentTOKENCOLON)298self。codedata。createcode()299self。parse(operator,inloopor(operatorinTOKENKEYLOOP))300break301添加控制语句及内部语句体ifforwhile302self。codedata。appendstatement(contentTOKENCOLON)303self。codedata。createcode()304self。parse(operator,inloopor(operatorinTOKENKEYLOOP))305else:306raiseParseException(Unkownbrace)307return308309defcompiledcode(self):310生成编译code311self。codedata。buildcode(self。filename)312ifnamemain:313tTemplate(html{{hello}}html)314t。render(hello你好
  原文链接:
  http:www。cnblogs。comjeffxunp15585073。html

开局10分钟,即成TOP3!realme何以在618大战中表众所周知,realme自成立以来发展速度一直都非常之快。例如,在取得单月销量突破百万的成绩之后,这个全球成长最快的智能手机品牌前些阵子又在发布会上边对外宣称要在今年618大战之……价格不贵且游戏体验不差的手机有没有?iQOOZ3可以了解下转瞬间已至年中七月,随着高考、中考的结束,以及各学校暑期的来临,相信不少小伙伴都和我一样开始蠢蠢欲动了。与忙碌的寒假不同,相比之下我个人更喜欢过暑假,虽然室外那炙热的天气不适宜……蚂蚁没能上的科创板,干孙子微众信科能上吗?蚂蚁金服折戟科创板和港股,是马爸爸最大的遗憾,2万亿啊,换谁都遗憾。失之东隅收之桑榆,这科创板的梦想没准可以靠干孙子微众信科实现了。是的,开在深圳,名字里面带微众的……互利共赢!远东控股与中电二公司签署战略合作协议10月27日,远东控股集团创始人、董事局主席、党委书记蒋锡培率队参访中国电子系统工程第二建设有限公司(简称:中电二公司),双方签订战略合作协议。战略合作签约仪式中电……ColorOS率先适配Android10,部分老机型用户即将9月3日,谷歌正式发布了Android10的稳定版,通过此次更新带来了一些以往安卓系统不曾拥有的一些系统特性,同时在用户隐私安全以及实用体验上都有着稳步的提升。而在9月24日,……从最年轻的世界500强到进步最快的世界500强,中国这家企业中国一流的公司在世界范围内的比重逐年提升,过往有不少人看不起中国产品,买什么都喜欢外国名牌,小到鞋子衣服,大到家电汽车,买手机就选苹果三星等等,仿佛在我们生活中司空见惯。……车险理赔考试1000题(含答案)第一季1。我国的第一部《保险法》颁布于哪一年?(A)A。1995B。1996C。1997D。19992。保险合同是投保人与保险人约定保险权利义务关系的(A)A。协议……新宝骏RS3喜提7项同级冠军,有颜值有实力,适合年轻人CCPC,全称中国量产车性能大赛,是中国量产车性能顶级赛事,旨在为用户购车提供参考,而其凭借一流的权威性、专业性,被誉为汽车界的奥运会;所以,CCPC在汽车行业的地位可以说是非……任天堂计划将京都一座工厂翻修成展厅,展示公司历史和产品品玩6月2日讯,据TheVerge消息,任天堂日前宣布,旗下UjiOgura工厂将变成一个公共展览厅,以展示任天堂在其历史上推出的众多产品。该工厂位于京都郊外Uji的Ogura……用胶卷拍照,底片最高分辨率都相当于哪个级别的数码相机?胶片的分辨率是分子级的,理论上可以近乎无限放大,这只是理论上,实际使用中是不可能的。数码相机会产生噪点,胶片会产生颗粒。颗粒跟噪点一样,都会影响画质。胶片的颗粒产生与冲洗……基于人工智能技术机器人做出人类面部表情尽管我们的面部表情在建立信任方面发挥着巨大的作用,但大多数机器人的面部表情仍然像职业扑克玩家一样空白、静止。在机器人和人类需要密切合作的地方,越来越多地使用机器人,对反应更快、……反制开始了,先是爱立信,再是美企,中科院捍卫中国芯片技术受美国影响之后,一些国家已经与华为的5G取消了合作。面对这样的情况,我国也开始进行反制,先是影响爱立信在国内的销量下滑,再是美企对华为进行赔偿,现在中科院也开始捍卫我国的芯片技……
手机市场下半年必迎涨价潮?高通中国区董事长孟璞:缺芯这个局面还将持续一段时间5月21日,高通举办了2021高通技术与合作峰会。在这个峰会上,高通中国区董事长孟璞不但向大家描绘了未来的愿景,也针对缺……江苏车主提了台比亚迪宋PLUS新能源,驾驶4200公里,有许江苏车主提了台比亚迪宋PLUS新能源,驾驶4200公里后,有许多话要说。我是江苏车主,提的是2021款DMi110KM旗舰型,裸车价格为15。88万元,目前已经行驶了42……超级推荐大改版,阿里妈妈引力魔方上线大家心心念念的超级推荐大改版终于来了!最近,阿里妈妈核心产品【超级推荐】进行了重大产品升级,升级为【阿里妈妈引力魔方】。新产品在原有强大信息流资源下,引入了手淘首页……realmeFlash,安卓首款磁吸无线充电手机本期内容应前几期粉丝留言投稿,所以小编带各位小伙伴来了解一下这款安卓首款磁吸无线充电手机!真我Flash这款手机性能方面,可能搭载了高通骁龙888plusLPDDR5UF……华为放大招了或将启用D系列旗舰机型,D10系列强势归来朋友们,大家好!欢迎您点开笑呵呵的小丑的文章,您的每一次浏览都是对小编最大的鼓励!事不宜迟,咱们进入本篇的正题。说到华为,不得不说它在今年的表现可谓是一波未平又起一波。首……红米们感受下OPPO子品牌Realme杀回国内针对不同市场推出子品牌俨然已经成了手机厂商们的通用套路,尤其是蓝绿大厂OV近期动作频频。这边厢,vivo高调打造了iQOO;那边厢,OPPO运作已久的Realme也亮出了獠牙。……快人一步我是专业的!罗技无线蓝牙键鼠打造移动办公黑科技一、写在前面大家好,我是你们的oak酱!和大多数商务工作者一样,我需要经常坐在电脑前,回家之后我也常加班,另外,我会趁着周末码字分享生活好物给大家讲真,键鼠使……焕新升级为智趣而来17。48万1TA系列上市新四化浪潮席卷之下,新能源汽车正在重构人们对于未来出行的想象。9月26日,广汽本田2022款VE1TA系列上市发布会召开。作为广汽本田首款纯电SUV,VE1开启了广汽本田电动化……域乎春节抽奖活动,赢取iPhone12等大礼新年快乐Happynewyear为回馈广大用户对域乎鲸矿的信任和鼓励,特推出春节抽奖活动,活动时间是2021年2月8日09:002021年2月14日20:00……AppStore限免通讯录备份和导出多合一照片等,共5款在今天限免的iOS限免应用中,波老师精选了以下5款限免应用。复制logo上方名字即可前往AppStore下载。如遇恢复原价,则表示限免已结束,请谨慎下载。具体下载方式:复……拿铁是VV6中期改款?续航高达1000Km,满满科技感你心动长城集团这些年来旗下的矩阵品牌都散发着各自的魅力,哈弗以亲民且实用一直受消费者爱戴;坦克则是新晋网红,凭借硬派气息保持着超高的热度;欧拉则抓住了女性的心理,迅速走红;魏牌则是最……WiFi相机FCC认证办理WiFi相机FCC认证办理步骤介绍。Wifi数码相机即相机带wifi功能,可以与wifi连接,让能通过网络更加便捷的上传或分享照片。但一般这类产品要出口美国则必须要办理FCC认……
友情链接:易事利快生活快传网聚热点七猫云快好知快百科中准网快好找文好找中准网快软网