模板语法有点像php

!/usr/bin/env python
""" #demo.py.html <html>
<?py include head.py.html ?>
<body>
<?py extend test_for.py.html ?>
<div>
<pre> test if </pre>
<?py if 2 > 1 ?>
<p>Yes, it is</p>
<?py else ?>
<p>No it is not</p>
<?py #endif ?>
</div> <div>
<pre> test def </pre>
<?py def p() ?>
<?py return 'hello' ?>
<?py #enddef ?>
Wow! ${p()}
</div>
</body>
</html> #head.py.html
<head>
<title>Demo Py Template</title>
</head> #test_for.py.html
<div>
<pre> test for <pre>
<?py for _ in ['a', 'b', 'c'] ?>
Hello ${_} #{_.upper()}
<?py #endfor ?>
</div>
""" from __future__ import absolute_import, division, print_function, with_statement
import re
import os.path class TemplateLoader(object):
pass class DictLoader(object):
pass class Template(object): #GLOBALS = {} def __init__(self, tempalte_path):
self.tempalte_path = tempalte_path self.globals = {
't': lambda x: x,
'xml_escape': xml_escape,
'html_escape': html_escape,
'e': escape
} self.templates = { } def render(self, path, **kwrags):
# the stemplae system local never be override
_g = kwargs.update(self.globals)
code = self.genarate(path, g)
exec code in _g
return _g['_tt_render']() def genarate(self, path, g):
if path in self.templates:
return self.templates[path](g) tempalte_path = os.path.join(self.tempalte_path, path)
tempalte_func = TemplateParser(tempalte_path).compile()
self.templates[path] = tempalte_func
return tempalte_func(g) class TemplateParser(object): PY_TOKEN = re.compile(r'<\?py\s*((?:[^=0-9]).*?)\s*\?>')
PY_VAR_TOKEN = re.compile(r'(?:[#$])\{(.*?)\}') def __init__(self, path2template, indent=None, include=False):
self.path2template = path2template
self.indent = indent or 1
self.buffer = ''
self._include = include
if not self._include:
self.buffer += 'def _tt_render():\n'
self.puts('_buffer=[]')
self.puts('_append=_buffer.append') def puts(self, line):
self.buffer += self.indents + "%s" % (line) + '\n' def compile(self):
code = self.parse()
code = compile(code, '<string>', 'exec', dont_inherit=True)
return code def parse(self):
f = open(self.path2template) lineno = 1
while True:
line = f.readline()
if not line:
break
self.parse_line(line, lineno)
lineno += 1
if not self._include:
self.puts('return "".join(_buffer)')
f.close() return self.buffer def parse_line(self, line, lineno): # remove the whitespace line and comment line
if not line.strip() or line.lstrip().startswith('#'):
return m = self.PY_TOKEN.search(line)
if m:
t = m.group(1)
parts = t.split(' ', 1)
if parts[0] in ('from', 'import'):
self.stmt(t)
return if parts[0] == 'include':
self.include(parts[1])
return if parts[0] == 'extend':
self.extend(parts[1])
return if parts[0] in ('for', 'if', 'with', 'def', 'class', 'try'):
self.contoll(t)
self.indent += 1
return if parts[0] in ('else', 'elif', 'except'):
self.indent -= 1
self.contoll(t)
self.indent += 1
return if parts[0] in ('#end', '#endfor', '#endif', '#endtry', '#endclass', '#enddef', '#endwith'):
self.indent -= 1
return self.stmt(t)
return # handle var token
ms = self.PY_VAR_TOKEN.finditer(line)
if ms:
a = None
end = 0
start = 0
l = ''
for m in ms:
t = m.group(1)
start = m.start() b = line[end:m.start()]
start = m.start()
end = m.end()
a = line[end:]
if l:
l += "+ '%s'" % (b) + " + str(%s) " % (t)
else:
l = "'%s'" % (b) + " + str(%s) " % (t) if a and start:
l += "+" + " %r" % (a)
if l:
self.stmt("_append(" + l + ")")
return self.text(line) def text(self, content):
content = self.indents + '_append(' + "%r" % (content) + ')\n'
self.buffer += content def e(self, formator, t):
self.puts('_append("' + formator + '"' + ' % ' + t + ")") def r(self):
return '%r' def contoll(self, line):
self.buffer += self.indents + line + ':\n' def stmt(self, stmt):
self.buffer += self.indents + stmt + ' \n' @property
def indents(self):
return ' ' * self.indent def include(self, template):
p = TemplateParser(template, include=True)
self.buffer += p.parse() def extend(self, template):
p = TemplateParser(template, self.indent, include=True)
self.buffer += p.parse() if __name__ == '__main__':
t = TemplateParser('demo.py.html') code = t.compile()
ns = {}
exec code in ns
# print ns
print(ns['_tt_render']())

用python写自定义模板的更多相关文章

  1. [Python自学] day-21 (1) (请求信息、html模板继承与导入、自定义模板函数、自定义分页)

    一.路由映射的参数 1.映射的一般使用 在app/urls.py中,我们定义URL与视图函数之间的映射: from django.contrib import admin from django.ur ...

  2. [python][django学习篇][15]博客侧栏--自定义模板标签

    我们的博客侧边栏有四项内容:最新文章.归档.分类和标签云. 这些内容相对比较固定,且在各个页面都会显示,如果像文章列表或者文章详情一样,从视图函数中获取然后传递给模板,则每个页面对应的视图函数里都要写 ...

  3. 【python】Django自定义模板函数

    参考:https://blog.csdn.net/wenyuanhai/article/details/73656761 注意: 1.自定义模板函数的路径必须为APP的templatetags下:ap ...

  4. Django——模板层(template)(模板语法、自定义模板过滤器及标签、模板继承)

    前言:当我们想在页面上给客户端返回一个当前时间,一些初学者可能会很自然的想到用占位符,字符串拼接来达到我们想要的效果,但是这样做会有一个问题,HTML被直接硬编码在 Python代码之中. 1 2 3 ...

  5. django “如何”系列4:如何编写自定义模板标签和过滤器

    django的模板系统自带了一系列的内建标签和过滤器,一般情况下可以满足你的要求,如果觉得需更精准的模板标签或者过滤器,你可以自己编写模板标签和过滤器,然后使用{% load %}标签使用他们. 代码 ...

  6. django自定义模板标签

    # 创建自定义模板标签目录 django_project_name app_name templatetags (创建Python Packge,注意一定要用templatetags这个名字) my_ ...

  7. [py]python写一个通讯录step by step V3.0

    python写一个通讯录step by step V3.0 参考: http://blog.51cto.com/lovelace/1631831 更新功能: 数据库进行数据存入和读取操作 字典配合函数 ...

  8. python---django中模板渲染(csrf令牌使用,自定义模板函数)

    使用终端,可以更方便的去实验,但是没有提示信息: 在项目目录下: D:\MyPython\day23\HelloWorld>python manage.py shell 开始实验: >&g ...

  9. Django 自定义模板标签和过滤器

    1.创建一个模板库 使用模板过滤器的时候,直接把过滤器写在app里,例如:在app里新建一个templatetags的文件夹,这个目录应当和 models.py . views.py 等处于同一层次. ...

随机推荐

  1. 使用VMwaver 克隆CentOS 6.9网卡配置报错

    报错信息: 克隆完成之后,使用的是NAT模式,进入系统之后有IP地址也可以ping外网,但是没有ifcfg-eth0这个文件,使用setup命令配置网卡时报以下错误: 待解决-

  2. 协程和I/O模型

    1.协程: 单线程实现并发 在应用程序里控制多个任务的切换+保存状态 优点: 应用程序级别速度要远远高于操作系统的切换 缺点: 多个任务一旦有一个阻塞没有切换,整个线程都阻塞在原地 该线程内的其他的任 ...

  3. 【HEVC简介】High Level Syntax

    参考文献:见<High Efficiency Video Coding (HEVC)>High Level Syntax章节 <HEVC标准介绍.HEVC帧间预测论文笔记>系列 ...

  4. Jenkins邮件扩展插件Email Extension Plugin配置使用

    1.在管理插件中搜索并安装邮件扩展插件Email Extension Plugin: 2.在任务中增加构建后操作步骤,选择Editable Email Notification; 3.在高级中Add ...

  5. 嵌入式ARM开发板学习方法步骤

    嵌入式开发就是指在嵌入式操作系统下进行开发,一般常用的系统有linux,android. 平台:Cortex-A9开发板 嵌入式技术学习如何入手,从何学起呢, 以下内容简单介绍嵌入式开发的学习步骤及如 ...

  6. mysql 函数tree状

    // 子节点的查询 CREATE DEFINER = `root`@`%` FUNCTION `getDeptChildList`(rootId BIGINT) RETURNS longtext DE ...

  7. Android studio Github 断开连接

    http://blog.csdn.net/agoodcoolman/article/details/50562301 使用软件:Android studio svn:Github 从github直接从 ...

  8. myBatis参数处理 myBatis佟刚课程笔记

    单个参数:myBatis不会做特殊处理 #{参数名}: 取出参数值 多个参数: myBatis会做特殊处理 多个参数会被封装成一个MAP key:param1 param2.... param10,或 ...

  9. linux(Ubuntu/Centos) iproute 路由IP地址等命令集合,查看端口链接

    原 linux(Ubuntu/Centos) iproute 路由IP地址等命令集合,查看端口链接 2017年03月20日 16:55:57 风来了- 阅读数:2291 标签: centoslinux ...

  10. Openjudge-百练-4013-踩方格

    这题目是一道深搜的题目,我们写一个递归函数叫Ways(int i, int j ,int n),i j就是当前所处的坐标,我们设置一个visited数组,简称 V . 对于这个数组,首先初始化为零,然 ...