Справка · Веб-версия · Шаблоны документов

Метки в шаблонах документов

Система рендерит акты и журналы по .docx/.dotx-шаблонам. В тексте шаблона расставляются метки в фигурных скобках, которые при формировании документа подменяются на реальные значения из БД.

Синтаксис меток — Jinja2 через библиотеку docxtpl (официальная дока).

Базовый синтаксис

Что Как написать в шаблоне
Подставить значение {{ order.number }}
Условный блок (если поле пустое — скрыть фразу) {% if order.description %}Описание: {{ order.description }}{% endif %}
Условный блок без пустого абзаца (рекомендуется) {%p if customer.kpp %}КПП: {{ customer.kpp }}{%p endif %}
Цикл по списку (например внутри таблицы) {%tr for item in items %}…{%tr endfor %}

⚠️ Важно: набирай метки вручную с клавиатуры, не вставляй через копипаст из браузера или PDF. Word может разрезать {{ и }} на разные текстовые «run»-блоки внутри XML, и docxtpl потеряет границы метки.


Словарь для актов заявок

Доступно в шаблонах, которые привязаны к типам заявок (Справочники → Виды заявок).

order.* — данные заявки

Метка Значение Пример
{{ order.number }} Номер заявки 2026-001
{{ order.created_at }} Дата создания 07.06.2026
{{ order.description }} Описание / задание Заменить датчик дыма

contract.* — договор

Метка Значение Пример
{{ contract.number }} Номер договора 12/2026-ТО
{{ contract.date_of_consclusion }} Дата заключения 01.06.2026
{{ contract.date_of_completion }} Дата завершения 31.12.2026
{{ contract.subject }} Полный предмет договора Техническое обслуживание систем АПС...
{{ contract.short_subject }} Краткое название ТО АПС

customer.* — заказчик

Метка Значение Пример
{{ customer.name }} Полное наименование Общество с ограниченной ответственностью «Ромашка»
{{ customer.short_name }} Короткое название ООО «Ромашка»
{{ customer.inn }} ИНН 7701234567
{{ customer.kpp }} КПП 770101001
{{ customer.director_full_name }} Директор в формате И.И. Иванов И.И. Иванов
{{ customer.address }} Юр. адрес одной строкой 101000, г. Москва, ул. ..., д. 1

executor.* — исполнитель

Поля идентичны customer.*{{ executor.name }}, {{ executor.inn }} и т.д.

object.* — объект (где будут работы)

Метка Значение Пример
{{ object.name }} Название объекта Бизнес-центр «Альфа»
{{ object.address }} Адрес объекта 101000, г. Москва, ул. ..., д. 5
{{ object.responsible_face }} Ответственное лицо на объекте Петров П.П.
{{ object.responsible_faces_contact }} Контакт ответственного +7 (495) 123-45-67

user.* — пользователь, который формирует акт

Метка Значение Пример
{{ user.full_name }} ФИО Сидоров С.С.
{{ user.role_name }} Роль Инженер ТО

qr — QR-код заявки для мобильного приложения

Метка Значение Пример
{{ qr }} Картинка QR-кода со ссылкой на эту заявку в приложении AutoReport (~3×3 см) (в акте появится квадратный QR-код)

Инженер сканирует QR камерой из мобильного приложения (кнопка 📷 в шапке главного экрана) и попадает сразу в карточку заявки — не нужно искать её вручную.

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

Если хотите подпись рядом с QR — напишите её текстом в шаблоне, например:

{{ qr }}
Сканируйте QR-код в мобильном приложении AutoReport

Если в шаблоне метки {{ qr }} нет — QR в акт не попадёт (старые шаблоны продолжают работать как раньше).

Даты сегодня

Метка Значение Пример
{{ today }} Короткий формат 13.06.2026
{{ today_long }} Полный формат «13» июня 2026 г.

equipment_groups — оборудование объекта, сгруппированное по системам

Список разделов, каждый — это тип обслуживаемой системы (spec_system) и список единиц оборудования внутри.

Структура одного элемента списка:

{
  "index": 1,
  "system_name": "Система пожарной сигнализации",
  "rows": [
    { "index": "1.1", "name": "Извещатель ИП-212-89", "count": 12 },
    { "index": "1.2", "name": "Прибор приёмно-контрольный С2000", "count": 1 }
  ]
}

Оборудование без привязки к spec_system попадает в отдельный финальный раздел с system_name="Оборудование".

Как нарисовать такую таблицу в Word — см. ниже («Таблицы в актах»).


Таблицы в актах

docxtpl поддерживает циклы по строкам Word-таблиц через специальный синтаксис {%tr ... %}. Для двухуровневой таблицы (раздел → строки оборудования) используется вложенный цикл.

⚠️ Главное правило {%tr%}-разметки

В docxtpl 0.20.x строки с {%tr%}-тегами удаляются целиком. То есть {%tr for %} и {%tr endfor %} — это строки-маркеры: они исчезают из готового документа, превращаясь в обёртку {% for %}...{% endfor %} вокруг соседних строк.

Поэтому строку-маркер нельзя совмещать со строкой данных. Каждый {%tr for %} и {%tr endfor %} живёт в отдельной строке таблицы без данных, а строка(-и) с {{ ... }} — между ними.

Если положить {%tr for x in items %} в ту же строку, где {{ x.name }} — эта строка удалится вместе с данными, и цикл прокрутится «вхолостую» (таблица останется пустой). Это самый частый источник недоумения.

Простая таблица (одноуровневая)

Структура из 3 строк + шапка:

Строка Ячейка 1 Ячейка 2
0 — шапка Наименование
1 — маркер начала {%tr for row in some_list %} (пусто)
2 — шаблон строки данных {{ row.index }} {{ row.name }}
3 — маркер конца {%tr endfor %} (пусто)

При рендере строки 1 и 3 удалятся; строка 2 размножится по числу элементов в some_list.

Двухуровневая таблица: разделы + оборудование

Для актов ТО — заголовок раздела (название системы) и под ним список оборудования. Структура 7 строк (шапка + 4 строки-маркера + 2 строки-шаблоны):

Строка Ячейка 1 Ячейка 2 Ячейка 3
0 — шапка Наименование Кол-во
1 — маркер: открыть внешний цикл {%tr for group in equipment_groups %}
2 — section row (жирным) {{ group.index }}. {{ group.system_name }}
3 — маркер: открыть внутренний цикл {%tr for row in group.rows %}
4 — item row {{ row.index }} {{ row.name }} {{ row.count }}
5 — маркер: закрыть внутренний цикл {%tr endfor %}
6 — маркер: закрыть внешний цикл {%tr endfor %}

При рендере строки 1, 3, 5, 6 исчезают. Строка 2 повторяется по числу групп; строка 4 — по числу элементов внутри текущей группы.

⚠️ Важно:

  • Обе пары {%tr for %} / {%tr endfor %} — в одной Word-таблице. Если разнести по разным таблицам — циклы не свяжутся.
  • В одной ячейке нельзя совмещать {%tr endfor %}{%tr endfor %} — это закроет только один цикл (для одной строки), второй останется буквальным текстом и Jinja упадёт с Encountered unknown tag 'endfor'. Каждому endfor — своя строка.
  • Объединение ячеек (merge) в section-row иногда ломает повтор у docxtpl. Если видишь пустую таблицу, проверь сначала без merge.
  • Внутренний {%tr for row in group.rows %} использует переменную group из внешнего цикла — это нормальное вложение Jinja.
  • Жирность и форматирование делаются обычным Word-инструментом, docxtpl сохраняет их.

Готовый образец

В репозитории бэка есть генерируемый референс templates/blanks/example_two_level.docx (в git не закоммичен — лежит локально для отладки). Скрипт его создания — в истории чатов; при потребности можно перегенерировать через python-docx.

Если нужен плоский список без разделов

Вариант: вложенные {%tr%} оставляешь, но в section-строке не выводишь ничего из group. Тогда получишь просто список оборудования подряд.

Прямой плоский цикл одной строкой типа {%tr for group in equipment_groups %}{%tr for row in group.rows %} в одной ячейке не сработает — каждый {%tr%} применяется ко всей строке целиком, и два цикла на одной строке конфликтуют.

Условные блоки в таблицах

Если хочешь скрыть пустую секцию (когда group.rows пуст), на строке-маркере открытия внешнего цикла:

{%tr for group in equipment_groups if group.rows %}

Это валидный Jinja-синтаксис, docxtpl его поддерживает.


Словарь для журналов объектов

Доступно в шаблонах, которые привязаны к видам журналов (Справочники → Виды журналов).

Тот же набор кроме user.* и order.* — журналы привязаны к объекту, а не к заявке:

  • {{ object.* }} — все поля
  • {{ contract.* }} — все поля
  • {{ customer.* }} и {{ executor.* }} — все поля
  • {{ today }}, {{ today_long }}

Примеры шаблонных фраз

Шапка акта

АКТ № {{ order.number }} от {{ today_long }}

Исполнитель: {{ executor.name }}, ИНН {{ executor.inn }}
в лице директора {{ executor.director_full_name }},
действующего на основании Устава,
с одной стороны,

и

Заказчик: {{ customer.name }}, ИНН {{ customer.inn }}
в лице директора {{ customer.director_full_name }},
действующего на основании Устава,
с другой стороны,

составили настоящий акт о следующем:

Условный блок (показать строку только если поле заполнено)

{%p if customer.kpp %}КПП: {{ customer.kpp }}{%p endif %}

Если у заказчика не указан КПП — вся эта строка (вместе с абзацем) полностью исчезнет из готового документа. Если указан — появится «КПП: 770101001».

Подпись

От Исполнителя:                          От Заказчика:

____________________                     ____________________
{{ executor.director_full_name }}        {{ customer.director_full_name }}

М.П.                                     М.П.

Документ сформировал: {{ user.full_name }} ({{ user.role_name }})
Дата: {{ today }}

Связано

  • См. статью «Загрузка и редактирование шаблонов» — про процесс заливки готового шаблона в систему.