20 дек. 2009 г.

Django CMS – show_menu

UPD: Начиная с версии 2.1.0 beta загрузка меню тэгов происходит по новому (см. http://www.django-cms.org/news/2010/03/24/django-cms-210-beta-released/).

Сегодня попытаюсь рассказать о template tag’е show_menu в django-cms. Сам разбирался с ним методом научного тыка.

{% show_menu %}


Тэг генерирует меню навигации для текущей (выбранной, открытой) страницы.

Параметры

Show_menu принимает следующие необязательные параметры:
start_level - начальный уровень навигации,
end_level конечный уровень навигации,
extra_inactive – начальный уровень “дополнительной” навигации,
extra_active - конечный уровень “дополнительной” навигации
“Дополнительная” - это навигация по страницам, которые не являются прямыми потомками и предками текущей страницы.
Для этого тэга можно переопределить шаблон вывода, создав в шаблонах своего проекта свой шаблон cms/menu.html или передав в ещё один дополнительный параметр template. Пример:

{% show_menu 0 100 0 100 "my_new_cool_menu.html" %}


Играемся с уровнями навигации

Для тестирования работы тэга возьмем сайт-пример demo.concepter.ru, о котором я уже писал раньше. (UPD: сайта demo.concepter.ru больше нет). Итак, имеет исходное дерево сайта:
  • root 1
    • 1 level child (p, n)
      • 2 level child (p, n) of 1
      • 2 level child (p) of 1
    • 1 level child (p)
      • 2 level child (p, n) of 1 level child (p)
    • 1 level child
    • 1 level child (n)
  • root 2
    • 1 level child (p, n) of root 2
      • 2 level child (p, n) of 1 of root 2
    • 1 level child (p) of root 2
буквы в скобках – статусы. p – страница опубликована, n – “в навигации”.
На главной странице вызваны show_menu со следующими параметрами:

1. {% show_menu 0 100 100 100 %} - Вся навигация



2. {% show_menu 0 100 0 100 %} - Навигация по активному дереву



3. {% show_menu 0 100 0 1 %} - Навигация с одним дополнительным уровнем



4. {% show_menu 0 0 0 0 %} - Корневая навигация



5. {% show_menu 1 1 100 100 %} - Навигация первого уровня



6. {% show_menu 1 1 0 100 %} - Навигация по первому уровню (только активное дерево)



7. {% show_menu 0 1 100 100 %} - Навигация по перевому и второму уровню


Под активным деревом в данном случае понимаем дерево, в которое входит выбранная страница. Например, потомков root 1 активным деревом будет все, что ниже root 1 и root 1, включительно.

Независимые от активной страницы блоки навигации

Естественно, что вся навигация (1), корневая навигация (4), навигация первого уровня (5) и навигация 0-1 уровней (7) не будут меняться с изменением активной страницы (т.е. при переходе на новую страницу). Потому сразу покажу, как они выглядят для всех страниц:

Complete navigation

Level 0 navigation

Level 1 navigation

Level 0-1 navigation

Навигацию по активному дереву


{% show_menu 0 100 0 100 %}


Далее посмотрим какие страницы попадут в навигацию по активному дереву в зависимости от смены страницы.
1. root 1
2. root 2
Активное дерево развернуто, а не активное – нет. В навигации все страницы с параметрами страница “опубликована” и “в навигации”.

Навигация с одним дополнительным уровнем


{% show_menu 0 100 0 1 %}


1. root 1
2. root 2
3. 1 level child (p, n)
4. 1 level child (p, n) of root 2
В навигации есть все, что опубликовано и одновременно присутствует в навигации. Тэг честно вываливает 1 дополнительный уровень к текущей странице (потомки).

Навигация по первому уровню (только активное дерево)


{% show_menu 1 1 0 100 %}


Такой тип навигации можно использовать в паре с навигацией 0-го уровня для генерации двухуровневого меню на главной странице, как тут:
image
image
Естественно, там сделано не так, но для примера подойдет.
Далее пары “Активная страница” + содержимое навигации:
root 1 + 1 level child (p, n)
root 2 + 1 level child (p, n) of root 2
1 level child (p, n) + 1 level child (p, n)
2 level child (p, n) of 1 + 1 level child (p, n)
1 level child (p, n) of root 2 + 1 level child (p, n) of root 2
2 level child (p, n) of 1 of root 2 + 1 level child (p, n) of root 2
Очевидно, что в навигации данного типа меню присутствует первый уровень активного дерева. Как всегда, в неё попали только опубликованные страницы со статусом “в навигации”.

Резюме

С помощью данного тэга можно выстраивать навигацию любой сложности и вложенности, главное не запутаться в уровнях и активных деревьях.
Без параметров тэг инициализируется с 0 100 и 0 100, так что в некоторых случаях можно использовать просто {% show_menu %}.
Помимо show_menu в django-cms есть ещё show_menu_below_id, show_sub_menu и show_breadcrumb, использование которых может существенно сэкономить время и нервы. Хотя, какие там нервы? Django-cms – полнеищий fun.
Читайте все тоже самое, но на английском на странице http://www.django-cms.org/en/documentation/2.0/navigation/.

7 комментариев:

Alvein комментирует...

Эм.. а если мне пишут, что у меня инвалидный тег (Invalid block tag: 'show_menu') ? При этом {% load cms_tags %} подключен написан строкой выше.

Что делаю не так?

Ivan Markeev комментирует...

Скорей всего, проблема в версии django-cms. В 2.1.0 бета приложение "меню" вынесено отдельно. См. подробности тут: http://www.django-cms.org/news/2010/03/24/django-cms-210-beta-released/.

Unknown комментирует...

Ув знатоки, есть такая задача:

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

Насколько я понял сейчас при скрытии узла автоматически скрывается вся ветка.

И еще, версия всего этого барахла не свежее чем сам пост :)

Ivan Markeev комментирует...

А признак in_navigation у него есть? Этим признаком и правильной настройкой show_menu решить проблему не удается?

Unknown комментирует...

in_navigation есть, вообще насколько я понял нужно рутовому узлу in_navigation=False, public=True, а вложенным in_navigation=True, public=True

Хм, вроде сработало... но в карте сайта раздел пропал. Переформулируем проблему так - можно заставить show_menu показывать все разделы, даже если in_navigation=False?

Ivan Markeev комментирует...

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

Кстати, в одном из проектов я использовал шаблон меню, в котором была проверка id ноды. Шаблон можно передать последним параметром к show_menu.

Unknown комментирует...

Вроде в шаблон уже передается отфильтрованный список, дополнительную проверку добавить можно, а вот то чего там нет уже не добавить... ну или по крайней мере это уже костыль. А вот идея со своим темплейттегом очень даже изящная - show_sitemap.

Спасибо :)