首页 > 代码库 > 用python写自定义模板

用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_statementimport reimport 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写自定义模板