Шаблонный движок Python - PullRequest
       6

Шаблонный движок Python

4 голосов
/ 02 июня 2010

Возможно ли, если кто-нибудь поможет мне начать писать движок шаблонов python? Я новичок в python и, изучая язык, мне удалось написать небольшую инфраструктуру MVC, работающую на его собственном легком WSGI-подобном сервере.

Мне удалось написать скрипт, который находит и заменяет ключи для значений: (Очевидно, это не то, как мой сценарий структурирован или реализован. Это только пример)

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>\n'
html += '    Home | <a href="/hi">Hi ${name}</a>\n'
html += '  </body>\n'
html += '<html>'

Template(html).safe_substitute(dict(name = 'Arturo'))

Моя следующая цель - реализовать пользовательские операторы, модификаторы, функции и т. Д. (Например, цикл for), но я не знаю, стоит ли мне использовать другой модуль, о котором я не знаю. Я думал о регулярных выражениях, но я чувствую, что это не будет эффективным способом сделать это

Любая помощь приветствуется, и я уверен, что она будет полезна и другим людям.

Спасибо

Ответы [ 3 ]

18 голосов
/ 02 июня 2010

Существует множество мощных языков шаблонов, поддерживаемых Python. Я предпочитаю Jinja2 . Также взгляните на Мако и Генши .

Mako - самый быстрый из трех, но его идеология позволяет иметь сложную кодовую логику прямо в шаблоне, которая время от времени провоцирует нарушение принципов MVC.

У Генши отличная концепция, особенно мощной особенностью является обратное наследование шаблонов. Но он самый медленный среди трех, и, как показывает практика, в реальном проекте все его функции часто бывают перебором.

Jinja2 - золотая середина, по моему личному мнению. Он легко расширяемый, довольно быстрый и знакомый для многих, поскольку использует синтаксис, похожий на шаблоны Django и Liquid язык шаблонов.

4 голосов
/ 02 июня 2010

хорошо, так как вы сказали, что вы новичок в Python, и ЕДИНСТВЕННАЯ причина, по которой вы пишете новую инфраструктуру MVC и движок шаблонов с нуля, заключается в целях обучения, вам не следует беспокоиться о производительности, IMHO.

Но если вы решили запустить что-то в производство, вам следует подумать об использовании уже существующих шаблонизаторов, таких как jinja2, mako, genshi и т. Д.

В любом случае, если вы хотите поиграть, есть хороший примерОблегченная веб-среда Python по адресу: http://github.com/breily/juno

и шаблонизатор световой скорости на http://github.com/eklitzke/spitfire

счастливого взлома!

1 голос
/ 02 июня 2010

Что ж, когда я решаю поиграть, как ты, TDD - это всегда хороший способ.

Итак, почему бы не попробовать?

например, создайте файл с именем jturo_template.py и напишите:

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()

Извините за длинный пост, но я думаю, вы можете попробовать этот рабочий процесс:

  1. написать тест, который не прошел
  2. запустить и посмотреть, как это не получится
  3. написать код для прохождения теста
  4. беги снова и смотри, как он проходит
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...