Python template engine
Could it be possible if somebody could help me get started in writing a python template engine? I'm new to python and as I learn the language I've managed to write a little MVC framework running in its own light-weight-WSGI-like server.
I've managed to write a script that finds and replaces keys for values: (Obviously this is not how my script is structured or implemented. this is just an example)
from string import Template
html = '<html>\n'
html += ' <head>\n'
html += ' <title>This is so Cool : In Controller HTML</title>\n'
html += ' </head>\n'
html += ' <body&开发者_如何转开发gt;\n'
html += ' Home | <a href="/hi">Hi ${name}</a>\n'
html += ' </body>\n'
html += '<html>'
Template(html).safe_substitute(dict(name = 'Arturo'))
My next goal is to implement custom statements, modifiers, functions, etc (like 'for' loop) but i don't really know if i should use another module that i don't know about. I thought of regular expressions but i kind feel like that wouldn't be an efficient way of doing it
Any help is appreciated, and i'm sure this will be of use to other people too.
Thank you
There are many powerful template languages supported by Python out there. I prefer Jinja2. Also take a look at Mako and Genshi.
Mako is fastest among three, but it's ideology allows to have a complex code logic right in template that provoke MVC principles violation from time to time.
Genshi has excellent conception, especially powerful feature is inversed template inheritance. But it is slowest among three and as practice shows all its features are often overkill in real project.
Jinja2 is a golden middle in my personal opinion. It is easily extensible, quite fast and familiar to many since it use syntax similar to Django templates and Liquid template language.
well, as you said you are a python rookie, and the ONLY reason you are writting a new MVC framework and template engine from scratch, is for learning purposes, you should not care about performance IMHO.
But if you decide to put something in production, you should consider using already existent template engines, such as jinja2, mako, genshi and so on.
Anyway if you want to play around, there is a nice example of lightweight web python framework at: http://github.com/breily/juno
and lightspeed template engine at http://github.com/eklitzke/spitfire
happy hacking!
Well, when I decide to play around like you did, TDD is always a good way to go.
so, why not give it a go?
for example, create a file called jturo_template.py and write:
import re import unittest class JTuroTemplate(object): u"""JTuro's template engine core class""" variable_regex = r'\$\{((.*)(%s)([^}]*))*\}' def __init__(self, string): self.string = string def __repr__(self): pieces = self.string.split() if len(pieces) > 3: head = "%s ..." % " ".join(pieces[:3]) else: head = " ".join(pieces) return u'<JTuroTemplate: "%s">' % (head) def render(self, context): new = unicode(self.string) for key, value in context.items(): variable_name = re.escape(key) regex = re.compile(self.variable_regex % variable_name) for match in regex.findall(new): if match[0]: replacement = match[0].replace(key, repr(value)) new = new.replace('${%s}' % match[0], unicode(eval(replacement))) return new class TestJTuroTemplate(unittest.TestCase): def test_repr(self): "a instance will be nicely represented" jt = JTuroTemplate('my template') self.assertEquals(repr(jt), '<JTuroTemplate: "my template">') def test_repr_truncated(self): "the python representation is truncated after 3 words" jt = JTuroTemplate('such a long string template') self.assertEquals(repr(jt), '<JTuroTemplate: "such a long ...">') def test_solves_simple_variables(self): "it solves simple variables" jt = JTuroTemplate('my variable is ${var} == 4') self.assertEquals(jt.render({'var': '4'}), 'my variable is 4 == 4') def test_solves_variables_with_python_code(self): "it solves variables with python code" jt = JTuroTemplate('my variable is ${var + var} == 44') self.assertEquals(jt.render({'var': '4'}), 'my variable is 44 == 44') if __name__ == '__main__': unittest.main()
Sorry for the long post, but I think you can try this workflow:
- write test that fail
- run and watch it fail
- write code to make the test pass
- run again and watch it pass
精彩评论