Как установить значение переменной внутри кода шаблона?

133

Скажем, у меня есть шаблон

<html>
<div>Hello {{name}}!</div>
</html>

При тестировании было бы полезно определить значение переменной, не касаясь кода python, который вызывает этот шаблон. Поэтому я ищу что-то вроде этого

{% set name="World" %}     
<html>
<div>Hello {{name}}!</div>
</html>

В Django существует нечто подобное?

Теги:
django-templates

9 ответов

209
Лучший ответ

Вам, вероятно, нужен тег with.

{% with "World" as name %}     
<html>
<div>Hello {{name}}!</div>
</html>
{% endwith %}

ИЗМЕНИТЬ

Правильный способ использования тега с тегом теперь: (старый формат по-прежнему поддерживается)

{% with name="World" greeting="Hello" %}     
<html>
<div>{{ greeting }} {{name}}!</div>
</html>
{% endwith %}
  • 19
    но вы можете изменить значение переменной в с?
  • 1
    Кажется, вы не можете объявить контейнер (я пробовал список и кортеж) в предложении с
Показать ещё 3 комментария
27

Альтернативным способом, который не требует, чтобы вы поместили все в блок "с", является создание настраиваемого тега, который добавляет новую переменную в контекст. Как в:

class SetVarNode(template.Node):
    def __init__(self, new_val, var_name):
        self.new_val = new_val
        self.var_name = var_name
    def render(self, context):
        context[self.var_name] = self.new_val
        return ''

import re
@register.tag
def setvar(parser,token):
    # This version uses a regular expression to parse tag contents.
    try:
        # Splitting by None == splitting by spaces.
        tag_name, arg = token.contents.split(None, 1)
    except ValueError:
        raise template.TemplateSyntaxError, "%r tag requires arguments" % token.contents.split()[0]
    m = re.search(r'(.*?) as (\w+)', arg)
    if not m:
        raise template.TemplateSyntaxError, "%r tag had invalid arguments" % tag_name
    new_val, var_name = m.groups()
    if not (new_val[0] == new_val[-1] and new_val[0] in ('"', "'")):
        raise template.TemplateSyntaxError, "%r tag argument should be in quotes" % tag_name
    return SetVarNode(new_val[1:-1], var_name)

Это позволит вам написать что-то вроде этого в вашем шаблоне:

{% setvar "a string" as new_template_var %}

Обратите внимание, что большая часть этого взята здесь

  • 0
    Как насчет присвоения переменных другим переменным, присутствующим в контексте? И еще одно замечание: разрешение шаблонам произвольно назначать контекстные переменные без проверки того, существуют ли они уже, может иметь последствия для безопасности. На мой взгляд, более разумным подходом будет проверка контекста для переменной перед попыткой назначить ее:
  • 0
    if context.get (self.var_name): повысить SuspiciousOperation («Попытка назначить переменную из шаблона, уже присутствующего в контексте»)
19

Есть трюки, подобные описанным Джоном; однако шаблон шаблона Django по дизайну не поддерживает установку переменной (см. поле "Философия" в Документация по Django для шаблонов).
Из-за этого рекомендуемый способ изменить любую переменную - это коснуться кода Python.

  • 7
    Спасибо за указатель. С точки зрения дизайнера, иногда проще быстро установить переменную для проверки различных состояний страницы при ее разработке. Не предлагать эту практику для использования в работающем коде.
  • 2
    тег "с" принят в django1.0. Похоже, они наконец-то исправляют свою философию :).
Показать ещё 1 комментарий
11

Создать тег шаблона:

Приложение должно содержать каталог templatetags на том же уровне, что и models.py, views.py и т.д. Если это еще не существует, создайте его - не забудьте файл __init__.py, чтобы убедиться, что каталог обработан как пакет Python.

Создайте файл с именем define_action.py внутри каталога templatetags со следующим кодом:

from django import template
register = template.Library()

@register.assignment_tag
def define(val=None):
  return val

Примечание. Сервер разработки не будет автоматически перезагружен. После добавления модуля templatetags вам необходимо перезагрузить сервер, прежде чем вы сможете использовать теги или фильтры в шаблонах.


Затем в вашем шаблоне вы можете назначить значения в контексте следующим образом:

{% load define_action %}
{% if item %}

   {% define "Edit" as action %}

{% else %}

   {% define "Create" as action %}

{% endif %}


Would you like to {{action}} this item?
  • 0
    работает отлично..!.
  • 1
    в моем случае после цикла это возвращает старое значение :(
Показать ещё 1 комментарий
7

Лучшим решением для этого является создание пользовательского assignment_tag. Это решение более чистое, чем использование тега with, поскольку оно обеспечивает очень четкое разделение между логикой и стилями.

Начните с создания файла тега шаблона (например, appname/templatetags/hello_world.py):

from django import template

register = template.Library()

@register.assignment_tag
def get_addressee():
    return "World"

Теперь вы можете использовать тег шаблона get_addressee в своих шаблонах:

{% load hello_world %}

{% get_addressee as addressee %}

<html>
    <body>
        <h1>hello {{addressee}}</h1>
    </body>
</html>
  • 1
    Для тех, кто использует более новые версии Django, его теперь называют simple_tag! Сэкономьте время, чтобы выяснить, почему "регистрация .." не распознается в вашем коде ...
3

Возможно, default фильтр шаблонов не был включен еще в 2009 году...

<html>
<div>Hello {{name|default:"World"}}!</div>
</html>
  • 0
    Сразу скажу, что это то, что я искал! Его также можно использовать с with : {% with state=form.state.value|default:other_context_variable %} вместо other_context_variable мы также можем использовать любое 'string_value'
  • 0
    Но он напечатает его, и мне нужно сохранить его для дальнейшего использования
3

Это не очень хорошая идея в целом. Сделайте всю логику на python и передайте данные в шаблон для отображения. Шаблон должен быть как можно более простым, чтобы те, кто работает над дизайном, могли сосредоточиться на дизайне, а не беспокоиться о логике.

Чтобы привести пример, если вам нужна какая-то производная информация в шаблоне, лучше получить ее в переменной в коде python, а затем передать ее вместе с шаблоном.

1

Используйте с инструкцией.

{% with total=business.employees.count %}
    {{ total }} employee{{ total|pluralize }}
{% endwith %}

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

1

В шаблоне вы можете сделать следующее:

{% jump_link as name %}
{% for obj in name %}
    <div>{{obj.helo}} - {{obj.how}}</div>
{% endfor %}

В тэгах шаблонов вы можете добавить тег следующим образом:

@register.assignment_tag
def jump_link():
    listArr = []
    for i in range(5):
        listArr.append({"helo" : i,"how" : i})
    return listArr

Ещё вопросы

Сообщество Overcoder
Наверх
Меню