Handlebars.js в шаблонах Django - PullRequest
       1

Handlebars.js в шаблонах Django

30 голосов
/ 29 августа 2011

Мне нужна система шаблонов javascript, и я думаю, что handlebars.js отлично справляется с этой задачей. У меня возникают синтаксические конфликты с шаблонами руля внутри шаблона django, потому что django пытается отобразить переменные руля.

Есть ли в шаблонах django тег для остановки рендеринга блока с фигурными скобками?

Что-то вроде:

{{ django_context_varable }} #works
{{% raw %}}
<script id="restaurants-tpl" type="text/x-handlebars-template">
    <ul>
    {{#restaurants}} #not rendered by django, plain text
    <li>{{name}}</li>
    {{/restaurants}}
    </ul>
</script>
{{% endraw %}}

Редактировать

Скорее всего, я нашел это . Работает нормально.

Обновление

Django 1.5 поддерживает тег дословно .

Ответы [ 8 ]

30 голосов
/ 29 августа 2011

Я использую пользовательский тег шаблона для другой системы шаблонов js, здесь: https://gist.github.com/629508

Использовать в шаблоне:

{% load mytags %}
{% verbatim %}
  {{ This won't be touched by {% django's %} template system }}
{% endverbatim %}

Редактировать: Этот пользовательский тег шаблона больше не нужен, поскольку язык шаблонов Django теперь поддерживает шаблонный тег {% verbatim%}.

20 голосов
/ 29 августа 2011

Есть ли в шаблонах django тег для остановки рендеринга блока с фигурными скобками?

СТАРЫЙ Ответ для Django 1.0-1.4: Нет, хотя вы могли бы поместить блок в отдельный файл и включить его без рендеринга или использовать другой шаблонизатор.

Новый ответ : Ответ выше был правильным в августе 2011 года, когда на вопрос был задан и дан ответ. Начиная с Django 1.5 (выпущенной в феврале 2013 года, хотя альфа / бета-версии были в конце 2012 года), они представили {% verbatim %} и {% endverbatim %}, которые не позволят обработчику шаблонов django обрабатывать содержимое в блоке.

Итак, для заданного вопроса в django 1.5+ из коробки будет работать следующее:

{{ django_context_varable }} #works
{% verbatim %}
<script id="restaurants-tpl" type="text/x-handlebars-template">
    <ul>
    {{#restaurants}} #not rendered by django, plain text
    <li>{{name}}</li>
    {{/restaurants}}
    </ul>
</script>
{% endverbatim %}

Документация по дословно здесь . Да, это было отмечено другими ранее, но так как это принятый ответ, я должен перечислить самое простое решение.

3 голосов
/ 16 марта 2012

Я написал очень маленькое приложение django: django-templatetag-handlebars именно для этой цели.

{% load templatetag_handlebars %}

{% tplhandlebars "tpl-infos" %}
    {{total}} {% trans "result(s)." %}
    <p>{% trans "Min" %}: {{min}}</p>
    <p>{% trans "Max" %}: {{max}}</p>
{% endtplhandlebars %}

Визуализируйте свой блок как обычно, используя Handlebars.js API:

var properties = {
    total: 10,
    min: 5,
    max: 4
};

var template = Handlebars.compile($('#tpl-infos').html()),
    rendered = template(properties);

Я написал это в тот день, когда @chrisv опубликовал свой пакет, имея в виду подход KISS. Это в основном основано на сути Мигеля Араужо: https://gist.github.com/893408.

3 голосов
/ 18 февраля 2012

для более глубокой интеграции между рулем и Django (включая дополнительную предварительную компиляцию на лету), посмотрите мой проект на https://bitbucket.org/chrisv/django-handlebars/

Это в основном работает так:

  1. создать шаблон HB под

    appdirectory/hbtemplates/myapp/template.html
    

    (так же, как шаблон Django)

  2. в вашем приложении используйте

    {% handlebars myapp %} 
    

    шаблон тега и шаблон рендеринга выглядят так:

    Handlebars.templates["myapp.template.html"]({context:"value"});
    
2 голосов
/ 07 марта 2017

Сначала скомпилируйте руль!

Из документации по предварительной компиляции руля :

Помимо уменьшения размера загрузки, устранение компиляции на стороне клиента значительно ускорит время загрузки, поскольку компиляция является самой дорогой частью Handlebars.

Вы можете скомпилировать шаблоны в вашей среде сборки, используя модуль handlebars npm , или интегрировать его с инструментом сборки, таким как gulp с gulp-handlebars .

После компиляции ваши шаблоны руля могут использоваться как статические ресурсы и вообще обходить рендеринг на стороне сервера. Облегчает кеширование тоже:)

Типичное использование будет выглядеть так:

<div id="restaurants-tpl">
    Waiting for content...
</div>

<script src="{% static 'js/handlebars.runtime.js' %}"></script>
<script src="{% static 'js/templates.js' %}"></script>
<script>
    // Let django render this as a json string
    properties = {{ properties }};

    // Use Handlebars compiled template imported above
    rendered_html = Handlebars.templates["restaurants-tpl"](properties);

    // Set element content 
    document.getElementById("restaurants-tpl").innerHTLM = rendered_html;
</script>
1 голос
/ 23 апреля 2013

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

from django import template
register = template.Library()
def handlebars(value):
    return '{{%s}}' % value
register.filter('handlebars', handlebars)

и используйте его в шаблоне примерно так:

{{"this.is.a.handlebars.variable"|handlebars}}

Это самая простая вещь, о которой я мог подумать. Вы просто должны поместить имя переменной вашего руля в кавычки. Я сожалею, что у меня не было этой идеи, прежде чем я боролся с SSI. Работает также с ключевыми словами:

{{"#each items"|handlebars}}
1 голос
/ 29 августа 2011

Система шаблонов Django не поддерживает экранирование блоков одновременно.Было бы легко обойти эту проблему, если бы не тот факт, что при обработке шаблонов токенизатор не хранит точную информацию о том, как выглядели токены до их токенизации.

Я использовал следующую работу:вокруг которого некрасиво, но (вроде) работает.Используйте различные разделители тегов в своих шаблонах и тег шаблона django, который переводит их обратно в то, что вы на самом деле хотите:

@register.tag(name="jstemplate")
def do_jstemplate(parser, token):
    while self.tokens:
        token = self.next_token()
        if token.token_type == TOKEN_BLOCK and token.contents == endtag:
            return
    self.unclosed_block_tag([endtag])
    nodelist = parser.parse( ('endjstemplate',) )
    parser.delete_first_token()
    s = token.split_contents()
    tmpl_id = Variable( s[1] ) if (len(s) == 2 and s[1]) else ''
    return JsTemplateNode( nodelist, tmpl_id )

class JsTemplateNode(template.Node):
    def __init__(self, nodelist, tmpl_id=''):
        self.tmpl_id = tmpl_id
        self.nodelist = nodelist
    def render(self, context):
        content = self.nodelist.render(context)
        return u'<script id="%s" type="text/x-handlebars-template">%s</script>' % (
                self.tmpl_id.resolve(context),
                re.sub( ur'{\$(.*?)\$}', u'{{\\1}}', content ), )

Для получения бонусных баллов вы можете использовать шаблоны Django в своих шаблонах ... что, вероятно, приготовит вашимозг пытается распутать позже:

{% jstemplate "restaurants-tpl" %}
{$#restaurants$}
<div id="<$name$<" class="{$type$}">
    <ul class="info">
        {$#if info/price_range$}<li><em>{{ trans "Price Range" }}:</em> {$info/price_range$}</li>{$/if$}
        {$#if info/awards$}<li><em>{{ trans "Awards" }}:</em> {$info/awards$}{$/if$}
    </ul>
    <div class="options">
        <button>{% trans "Reservation" %}</button>
    </div>
</div>
{$/restaurants$}
{% jstemplate %}
1 голос
/ 29 августа 2011

Почему бы не использовать jinja2 вместо этого? ИМО, они оба элегантны в использовании. Вот отличная статья об этом: Использование Jinja2 с Django

...