Как использовать шаблоны в формах
Можно подставлять динамические данные в заявки из форм Shtab
Когда форма привязана к источнику данных и типу задачи, при каждой отправке формы автоматически создаётся задача. Название и описание задачи формируются из шаблонов с помощью встроенного шаблонизатора.
Как работает генерация названия и описания
- Пользователь отправляет форму.
- Система берёт шаблон названия (
name_template) и шаблон описания (description_template) из настроек формы. - Подставляет в них значения из ответа — данные полей, информацию об отправителе.
- Результат рендера
name_template→ название задачи. - Результат рендера
description_template→ HTML-описание задачи (документ). - Если шаблон названия пуст или после рендера содержит только пробелы — название задачи будет
Form submission #<id>.
Переменные шаблона
В шаблонах доступны следующие переменные верхнего уровня:
| Переменная | Тип | Описание |
|---|---|---|
submission |
объект | Данные об отправке формы |
fields |
объект | Значения полей формы (по slug-имени) |
Переменная submission
Содержит информацию об отправке. Доступные атрибуты:
| Атрибут | Тип | Описание |
|---|---|---|
id |
число | ID отправки |
anonymous_name |
строка | Имя анонимного отправителя (если форма публичная) |
anonymous_email |
строка | Email анонимного отправителя |
created_at |
дата и время | Дата и время отправки |
user |
объект или "" |
Авторизованный пользователь (или пустая строка) |
Любой другой атрибут вернёт пустую строку. Данные защищены — получить доступ к полям, не входящим в список, невозможно.
Пример:
Отправка #{{ submission.id }} от {{ submission.created_at|date:"d.m.Y H:i" }}
Результат: Отправка #42 от 15.03.2026 14:30
Переменная submission.user
Если форму отправил авторизованный пользователь, доступны:
| Атрибут | Тип | Описание |
|---|---|---|
id |
число | ID пользователя |
username |
строка | Логин |
first_name |
строка | Имя |
last_name |
строка | Фамилия |
email |
строка |
Любой другой атрибут вернёт пустую строку.
Пример:
{{ submission.user.first_name }} {{ submission.user.last_name }} ({{ submission.user.email }})
Результат: Иван Петров (ivan@example.com)
Если пользователь не авторизован, submission.user вернёт пустую строку.
Переменная fields
Через fields вы обращаетесь к значениям полей формы по их slug-имени.
Пример:
{{ fields.company }}
Если поле с таким slug найдено — подставится значение из ответа. Если нет — пустая строка.
Как формируются slug-имена полей
Каждое поле формы имеет название (например, «Название компании»). Из этого названия автоматически генерируется slug — техническое имя для использования в шаблоне.
Алгоритм
- Название поля приводится к нижнему регистру.
- Пробелы заменяются на дефисы (
-). - Все символы, кроме букв, цифр, дефисов и подчёркиваний, удаляются.
- Если slug получился пустым — используется
field_<id>(гдеid— внутренний ID поля). - Если slug совпадает с уже существующим — добавляется суффикс
_1,_2и т.д.
Примеры преобразования
| Название поля | Slug в шаблоне | Использование в шаблоне |
|---|---|---|
Компания |
kompaniia |
{{ fields.kompaniia }} |
Company |
company |
{{ fields.company }} |
Full Name |
full-name |
{{ fields.full-name }} |
Email Address |
email-address |
{{ fields.email-address }} |
Телефон |
telefon |
{{ fields.telefon }} |
Name (первое) |
name |
{{ fields.name }} |
Name (второе) |
name_1 |
{{ fields.name_1 }} |
Name (третье) |
name_2 |
{{ fields.name_2 }} |
!!! |
field_57 |
{{ fields.field_57 }} |
Важно: Для кириллических названий полей slug формируется транслитерацией. Например, «Имя» →
imia, «Описание проблемы» →opisanie-problemy.
Как ведут себя значения полей
| Тип поля | Что подставляется |
|---|---|
| Текст, Многострочный текст | Строковое значение |
| Число | Число как строка |
| Дата | Дата как строка |
| Диапазон дат | Дата как строка |
| Email, Телефон, Ссылка | Строковое значение |
| Выбор, Радио | Значение выбранного варианта |
| Множественный выбор | Значения через запятую: вариант1, вариант2 |
| Файл (несколько) | ID файлов через запятую |
| Чекбокс | Строковое значение |
| Пользователь | Строковое значение (ID) |
| Пустое / не заполнено | Пустая строка |
Теги
Теги — это управляющие конструкции, которые позволяют добавить логику в шаблон. Записываются в {% %}.
if / elif / else — условие
Выводит содержимое только если условие истинно.
{% if fields.company %}Компания: {{ fields.company }}{% endif %}
{% if submission.user %}
Отправил: {{ submission.user.first_name }}
{% else %}
Отправил: {{ submission.anonymous_name }}
{% endif %}
{% if fields.priority == "high" %}
СРОЧНО: {{ fields.subject }}
{% elif fields.priority == "medium" %}
{{ fields.subject }}
{% else %}
{{ fields.subject }} (низкий приоритет)
{% endif %}
Поддерживаемые операторы в условиях: ==, !=, <, >, <=, >=, and, or, not, in, not in.
for — цикл
Перебирает элементы списка. Тег empty задаёт содержимое, если список пуст.
{% for item in fields.tags %}{{ item }}, {% empty %}нет тегов{% endfor %}
firstof — первое непустое значение
Выводит первое непустое значение из списка.
{% firstof fields.company fields.name submission.anonymous_name "Не указано" %}
Если fields.company пусто — выведет fields.name, если и оно пусто — submission.anonymous_name, и так далее.
now — текущая дата/время
Выводит текущую дату и время в заданном формате.
{% now "d.m.Y" %}
Результат: 15.03.2026
{% now "d.m.Y H:i" %}
Результат: 15.03.2026 14:30
cycle / resetcycle — чередование значений
Чередует значения при каждом вызове. Полезно в циклах.
{% for item in fields.items %}
<p class="{% cycle 'odd' 'even' %}">{{ item }}</p>
{% endfor %}
Фильтры
Фильтры изменяют отображение значения переменной. Записываются через символ | после переменной.
default — значение по умолчанию
Подставляет указанное значение, если переменная пуста или равна False.
{{ fields.company|default:"Не указано" }}
Если поле «Компания» не заполнено → Не указано.
default_if_none — значение по умолчанию если None
Подставляет значение только если переменная равна None (но не пустой строке).
{{ fields.comment|default_if_none:"Без комментария" }}
lower — в нижний регистр
{{ fields.name|lower }}
ИВАН → иван
upper — в верхний регистр
{{ fields.name|upper }}
иван → ИВАН
title — каждое слово с заглавной
{{ fields.name|title }}
иван петров → Иван Петров
capfirst — первая буква заглавная
{{ fields.comment|capfirst }}
срочная заявка → Срочная заявка
date — форматирование даты
Форматирует дату/время по заданному формату.
{{ submission.created_at|date:"d.m.Y" }}
Результат: 15.03.2026
{{ submission.created_at|date:"d F Y, H:i" }}
Результат: 15 марта 2026, 14:30
Основные символы формата:
| Символ | Значение | Пример |
|---|---|---|
d |
День (01–31) | 15 |
m |
Месяц (01–12) | 03 |
Y |
Год (4 цифры) | 2026 |
H |
Часы (00–23) | 14 |
i |
Минуты (00–59) | 30 |
s |
Секунды (00–59) | 00 |
F |
Название месяца | март |
l |
День недели | понедельник |
time — форматирование времени
Форматирует только временную часть.
{{ submission.created_at|time:"H:i" }}
Результат: 14:30
add — сложение
Прибавляет число к значению.
{{ fields.quantity|add:"10" }}
Если fields.quantity = 5, результат: 15.
cut — удаление подстроки
Удаляет все вхождения указанной подстроки.
{{ fields.phone|cut:" " }}
+7 999 123 45 67 → +799912345 67 → +79991234567
join — объединение списка
Объединяет элементы списка в строку через разделитель.
{{ fields.tags|join:", " }}
["python", "django"] → python, django
slice — срез
Возвращает часть строки или списка.
{{ fields.description|slice:":100" }}
Первые 100 символов описания.
{{ fields.name|slice:"0:5" }}
Первые 5 символов имени.
length — длина
Возвращает длину строки или списка.
{{ fields.tags|length }}
Если в fields.tags 3 элемента → 3.
first — первый элемент
Возвращает первый элемент строки или списка.
{{ fields.tags|first }}
last — последний элемент
Возвращает последний элемент строки или списка.
{{ fields.tags|last }}
center — центрирование
Центрирует строку в поле заданной ширины.
{{ fields.code|center:"20" }}
ljust — выравнивание влево
Выравнивает строку влево в поле заданной ширины.
{{ fields.code|ljust:"20" }}
rjust — выравнивание вправо
Выравнивает строку вправо в поле заданной ширины.
{{ fields.code|rjust:"20" }}
wordcount — количество слов
Возвращает количество слов в строке.
{{ fields.description|wordcount }}
Срочная заявка на ремонт → 4
timedelta — сдвиг даты/времени (кастомный фильтр)
Прибавляет к дате указанный интервал. Для использования нужно загрузить фильтр: {% load custom_filters %}.
{% load custom_filters %}
{{ submission.created_at|timedelta:"days=3" }}
Прибавит 3 дня к дате отправки.
{% load custom_filters %}
{{ submission.created_at|timedelta:"hours=2,minutes=30" }}
Прибавит 2 часа 30 минут.
Доступные параметры: years, months, days, hours, minutes, seconds. Можно комбинировать через запятую.
{% load custom_filters %}
{{ submission.created_at|timedelta:"years=1,months=6" }}
Полезные примеры
Название задачи с именем отправителя
{% if submission.user %}{{ submission.user.first_name }} {{ submission.user.last_name }}{% else %}{{ submission.anonymous_name|default:"Аноним" }}{% endif %} — {{ fields.subject|default:"Без темы" }}
Результат: Иван Петров — Проблема с оплатой
Описание задачи в HTML-формате
<h3>Заявка от {{ submission.created_at|date:"d.m.Y" }}</h3>
<p><strong>Компания:</strong> {{ fields.company|default:"—" }}</p>
<p><strong>Контакт:</strong> {{ fields.email|default:submission.anonymous_email }}</p>
<p><strong>Описание:</strong></p>
<p>{{ fields.description|default:"Не указано" }}</p>
Условное отображение полей
<p>{{ fields.name }}</p>
{% if fields.phone %}<p>Телефон: {{ fields.phone }}</p>{% endif %}
{% if fields.email %}<p>Email: {{ fields.email }}</p>{% endif %}
{% if fields.comment %}<p>Комментарий: {{ fields.comment }}</p>{% endif %}
Название задачи с ID формы
[Форма #{{ form_id }}] {{ fields.title|default:"Новая заявка" }}
Результат: [Форма #12] Запрос на доступ
Обрезка длинного описания для названия
{{ fields.description|slice:":80" }}{% if fields.description|length > 80 %}...{% endif %}
Форматирование даты отправки
{% load custom_filters %}
Отправлено: {{ submission.created_at|date:"d.m.Y в H:i" }}
Дедлайн: {{ submission.created_at|timedelta:"days=7"|date:"d.m.Y" }}
Результат: Отправлено: 15.03.2026 в 14:30 / Дедлайн: 22.03.2026
Часто задаваемые вопросы
Что будет, если переменная не существует?
Пустая строка. Шаблон не сломается — несуществующие переменные и атрибуты просто выводят "".
{{ fields.nonexistent_field }}
Результат: `` (пустая строка)
Что будет, если шаблон названия пуст?
Задача получит название Form submission #<id>, где <id> — номер отправки.
Можно ли использовать HTML в шаблоне описания?
Да. Шаблон описания рендерится как HTML и сохраняется в документе задачи.
<p><strong>{{ fields.name }}</strong></p>
<ul>
<li>Email: {{ fields.email }}</li>
<li>Телефон: {{ fields.phone }}</li>
</ul>
Как узнать slug-имя поля?
Slug формируется из названия поля автоматически: нижний регистр, пробелы → дефисы, спецсимволы удаляются. Кириллица транслитерируется. Если у двух полей одинаковые названия — к slug добавляется суффикс _1, _2 и т.д.
Рекомендация: давайте полям короткие латинские названия — name, email, company, description — тогда slug будет совпадать с названием.
Почему мой шаблон не сохраняется и возвращает ошибку?
Возможные причины:
- Синтаксическая ошибка — незакрытый тег
{% if %}без{% endif %}, неправильная конструкция.
Как вывести значение «по умолчанию», если поле не заполнено?
Используйте фильтр default:
{{ fields.company|default:"Компания не указана" }}
Как показать одно значение для авторизованного пользователя и другое для анонима?
{% if submission.user %}
{{ submission.user.first_name }} {{ submission.user.last_name }}
{% else %}
{{ submission.anonymous_name|default:"Аноним" }} ({{ submission.anonymous_email|default:"email не указан" }})
{% endif %}
Можно ли комбинировать несколько фильтров?
Да, фильтры можно объединять через |:
{{ fields.name|lower|capfirst }}
ИВАН ПЕТРОВ → иван петров → Иван петров
Как использовать фильтр timedelta?
Обязательно добавьте {% load custom_filters %} в начало шаблона:
{% load custom_filters %}
{{ submission.created_at|timedelta:"days=1"|date:"d.m.Y" }}
Без {% load custom_filters %} фильтр timedelta не будет доступен.