用python写自定义模板

模板语法有点像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‘]())
时间: 2024-11-02 18:51:55

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

使用python写一个监控mysql的脚本,在zabbix web上自定义模板

##先使用MySQLdb的接口关联数据库. [[email protected] python]# cat check_Mysql_custom.py #!/usr/local/bin/python '''author = chenmingle''' '''Description:get mysql status''' import os import sys try:     import MySQLdb as mysql except Exception, e:     print e   

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

1.创建一个模板库 使用模板过滤器的时候,直接把过滤器写在app里,例如:在app里新建一个templatetags的文件夹,这个目录应当和 models.py . views.py 等处于同一层次.例如: books/     __init__.py     models.py     templatetags/     views.py 在 templatetags 中创建两个空文件:一个 __init__.py (告诉Python这是一个包含了Python代码的包)和一个用来存放你自定义的

python写一个通讯录V2.0

python写一个通讯录step by step V2.0 引用知识 list + dict用于临时存储用户数据信息 cPickle用于格式化文件存取 依旧使用file来进行文件的存储 解决问题 1.操刀开始去做 原始代码 实现功能(可做模板) 1.判断输入内容是否在给出的menu目录内,在的话,返回对应结果,不在就报错 2.调用os模块的exit功能 3.字典配合循环加上函数实现switch的功能 #!/usr/bin/env python #coding:utf8 #Author:zhuim

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

django的模板系统自带了一系列的内建标签和过滤器,一般情况下可以满足你的要求,如果觉得需更精准的模板标签或者过滤器,你可以自己编写模板标签和过滤器,然后使用{% load %}标签使用他们. 代码布局 自定义标签和过滤器必须依赖于一个django app,也就是说,自定义标签和过滤器是绑定app的.该app应该包含一个templatetags目录,这个目录一个和model.py,views.py在同一个层级,记得在该目录下建立一个__init__.py文件一遍django知道这是一个pyth

自定义模板语言整合

这篇文章主要对比一下两大框架Tornado和Django自定义模块语言,以及对Tornado的自定义模块语言进行一个分离整合 首先我们先看一下在Tornado里,我怎么实现的自定义模板语言 第一步,创建UIMethods.py文件,写入自定义方法(第一参数一定为self),创建UIModules.py文件,定义类(必须继承Tornado一个导入类UIModule,通过重写render方法实现) 第二步,注册到settings里 第三步,在模板语言里调用  {{ 函数方法 }}  {% modul

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

python写一个通讯录step by step V3.0 参考: http://blog.51cto.com/lovelace/1631831 更新功能: 数据库进行数据存入和读取操作 字典配合函数调用实现switch功能 其他:函数.字典.模块调用 注意问题: 1.更优美的格式化输出 2.把日期换算成年龄 3.更新操作做的更优雅 准备工作 db准备 - 创建数据库 mysql> create database txl charset utf8; Query OK, 1 row affecte

Django之博客系统:自定义模板标签

Django提供了很多内置的模板标签比如{% if %}或者{% block %}Django也允许你创建自己的模板标签(template tags)来执行自定义的动作.当你需要在你的模板中添加功能而Django模板标签(template tags)的核心设置无法提供此功能的时候,自定义模板标签会非常方便 Django提供了以下帮助函数(functions)来允许你以一种简单的方式创建自己的模板标签(template tags): simple_tag:处理数据并返回一个字符串(string)

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

阅读目录(Content) 模板语法之变量 模板之过滤器 default length filesizeformat date slice truncatechars safe 模板之标签 自定义标签和过滤器 模板继承 (extend) 模板语法之include 前言:当我们想在页面上给客户端返回一个当前时间,一些初学者可能会很自然的想到用占位符,字符串拼接来达到我们想要的效果,但是这样做会有一个问题,HTML被直接硬编码在 Python代码之中. 1 2 3 4 def current_dat

django 第五课自定义模板过滤器与标签

代码布局:(自定义的代码放在哪里) 某个app特有的 app目录下,templatetags文件夹需要放 __init__.py 在到templetags文件夹下创建python模块(py文件) 定义复用 创建要给新的app,将他们定义在新的app中,在INSTALL_APPS 注册,然后可以应用 自定义模板过滤器 模板过滤器是什么? 函数,一个或两个参数 第一个参数是传递进来的模板变量 第二个参数,普通的参数,也可以是默认也可以不要其实就是个函数,没有什么不同在app目录teacher下创建t