Files
2018-lpon-site/_prj_blueprint/DSL.md
T

114 lines
7.2 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Спецификация: LPON Store Hub DSL (Компактный конструктор интерфейсов на кортежах)
драфт
## 1. Обзор и цели
Мы реализуем гибкий, управленный данными (Data-Driven) конструктор страниц внутри бэкенда Django для **LPON.RU**.
Вместо написания отдельных вьюх (Views) и шаблонов под каждый формат или раздел (например, `/catalog/cassettes/`, `/catalog/vinyl/`), мы формируем динамические **Страницы-Хабы (Hub Pages)** с помощью компактного JSON Tuple DSL, который хранится прямо в базе данных.
Система завязана на модель `TbArticle` с типом `l_article_type = 'HUB'`. Конфигурация хранится в JSON-поле метаданных статьи (`j_article_metadata['hub']`).
---
## 2. Синтаксис и структура JSON DSL
Массив `hub` представляет собой список позиционных кортежей (массивов). Движок определяет тип блока на основе длины массива и типов переданных значений.
### Правила синтаксиса:
```json
{
"hub": [
["source-slug", "view_mode"],
["source-slug", limit, "sort_rule", "view_mode"],
["module-or-article-slug"]
]
}
```
## 3. Спецификация блоков
### Тип A: Блок предложений товаров (по умолчанию Длина = 4)
Выводит подборку товаров (TbOffer), полученную на основе категории, тега формата или слаг-коллекции.
Формат: `[ "slug", limit, "sort", "view_mode" ]`
Параметры:
1. `slug` (str): Уникальный слаг TbMusicStyle, TbArticle (Категория/Тег) или идентификатор формата (например, cassettes-studio, cassettes-used-blank).
2. `limit` (int): Количество выводимых товаров (например, 5, 20). Фолбэк при ошибке: 10.
3. `sort` (str): Правило сортировки:
- `views` → -i_offer_views (самые просматриваемые)
- `favorites` → -i_offer_favorites (самые популярные / в избранном)
- `newest` → -t_offer_created (новинки)
- `price_asc` → f_offer_price (сначала дешевые)
- `price_desc` → -f_offer_price (сначала дорогие)
4. `view_mode` (str): Компонент рендеринга (шаблон):
- `carousel` → Горизонтальная карусель / слайдер.
- `grid` → Стандартная сетка карточек.
- `list` → Компактный вертикальный список.
Пример: ["cassettes-studio", 5, "views", "carousel"]
Замечания: `view_mode` -- это название зарегистрированного шаблона в системе. Если передан неизвестный `view_mode` или он отсутствует, используется дефолтный `list`.
### Тип B: Баннер / Вложенная статья / Вложенный хаб (Длина = 2)
Встраивает существующую статью, рекламный баннер или массив вложенного хаба.
Формат: [ "slug", "view_mode" ]
Параметры:
1. `slug` (str): Слаг целевой TbArticle.
2. `view_mode` (str): Режим отображения:
- `slider` / `hero` → Главный баннер / промо-слайдер.
- `teaser` → Тизер статьи с кнопкой «Читать далее».
- `full` → Полный HTML-контент статьи, встроенный inline.
Пример: ["hero-banner-cassettes", "slider"]
### Тип C: Динамический модуль / Плагин (Длина = 1)
Запускает кастомный Python-модуль, зарегистрированный в системе (например, расчет скидок, интерактивные виджеты, реклама).
Формат: [ "module-slug" ]
Параметры:
1. `slug` (str): Уникальный идентификатор, зарегистрированный в PluginRegistry (например, module-promo-mandarin, module-ad-banner-1).
Пример: ["module-promo-mandarin"]
## 4. Полный пример конфига (j_article_metadata)
{
"hub": [
["hero-cassettes-2026", "slider"],
["cassettes-studio", 6, "views", "carousel"],
["cassettes-studio", 20, "newest", "grid"],
["module-mandarin-promo"],
["cassettes-maxell-used-ud2-c90-ver2", 6, "popular", "carousel"],
["cassettes-tdk-ned-cding2-c60", 20, "price_desc", "list"],
["guide-how-to-clean-heads", "teaser"]
]
}
## 5. Защита и логика бэкенда (Требования к Python / Django)
При разработке парсера DSL:
1. Защита от зацикливания и бесконечной рекурсии:
- Передавать множество `visited_slugs` при рендере страницы.
- Если вложенный блок пытается загрузить `slug`, который уже есть в `visited_slugs`, пропускать блок или выводить отладочный HTML-комментарий (`<!-- DSL Error: Circular reference detected for slug -->`).
2. Ограничение глубины вложенности:
- Жестко ограничить максимальную глубину рекурсии: `MAX_RECURSION_DEPTH = 2` (устанавливается в `settings.py`).
3. Отказоустойчивость (Graceful Degradation):
- Если limit передан не числом или sort содержит неизвестную строку, парсер должен тихо применить безопасные дефолты (`limit=10`, `sort='newest'`, `view_mode='grid'`). Ошибка синтаксиса в JSON никогда не должна приводить к `500 Server Error`.
- Если `slug` не найден в базе, блок пропускается, а в HTML выводится комментарий: `<!-- DSL Error: Slug not found -->`.
4. Изоляция данных:
- Внутри DSL запрещено использовать сырые имена полей БД (например, k_offer_to_item__s_item). Все выборки данных маппятся строго через `slug` и внутренние обработчики запросов (Query Handlers).
- Все ключи из json['hub'] должны быть объявлены заранее.
5. Валидация slug
- Нужно добавить в валидатор админки статей (TbArticle) проверку на "не совпадение" slug с существующими роутами сайта из `'urls.py'` (чтобы не было конфликта URL-ов).