Подтвердить что ты не робот

Django: передача аргумента родительскому шаблону

У меня есть шаблоны этого стиля

project
- main_templates (including nav bar)
-- app1
--- app1_base_template
--- app1_templates
-- app2
--- app2_base_template
--- app2_templates

Поэтому при рендеринге app2_templates расширяет файл app2_base_template, который расширяет main_template.

Мне нужно сделать, чтобы соответствующий элемент навигации был выделен жирным шрифтом при визуализации шаблона app2 (чтобы показать пользователя, где он).

Проще всего было бы, если бы я мог передать переменную в части {% block xxx%}. Возможно ли это?

Какие еще общие способы существуют?

4b9b3361

Ответ 1

Вы пробовали тег шаблона {% with%}?

{% block content %}
  {% with 'myvar' as expectedVarName %}
  {{block.super}}
  {% endwith %}
{% endblock content %}

Ответ 2

Нет прямого способа передать переменную в дереве наследования шаблона так, как вы описываете. Способ, которым люди внедряют навигационные панели, которые выделяют текущую страницу, часто корректируется по характеру самого сайта. Тем не менее, я видел два общих подхода:

Низкотехнологичный подход

Передайте переменную в контексте шаблона, которая указывает, какая вкладка активна:

# in views.py
def my_view(request):
    return render_to_response('app2_template.html', {"active_tab": "bar"},

<!-- Parent template -->
<div id="navigation">
    <a href="/foo" {% ifequal active_tab "foo" %}class="active"{% endifequal %}>Foo</a>
    <a href="/bar" {% ifequal active_tab "bar" %}class="active"{% endifequal %}>Bar</a>
</div>

Высокотехнологичный подход

Внедрите пользовательский тег шаблона, чтобы отобразить панель навигации. Попросите тег взять переменную, которая указывает, какой раздел активен:

<!-- Parent template -->

<div id="navigation">{% block mainnav %}{% endblock %}</div>

<!-- any child template -->
{% load my_custom_nav_tag %}
{% block mainnav %}{% my_custom_nav_tag "tab_that_is_active" %}{% endblock %}

Вы можете сходить с ума оттуда. Вы можете обнаружить, что кто-то уже реализовал что-то, что будет работать на вас на djangosnippets.org.

Ответ 3

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

Ответ 4

Неспособность передать аргументы при включении шаблона является одним из многих недостатков системы шаблонов Django.

Мне приходилось сталкиваться с почти одинаковой проблемой: глубоко вложенные шаблоны, необходимые для того, чтобы родительские шаблоны могли форматировать/выделять по-разному.

Возможные решения:

  • Используйте подпрограмму "суперконтекст", которая устанавливает количество значений на основе того, где вы находитесь в иерархии. То есть super_context = MySuperContext (запрос, другие, значения и т.д.), где super_context - это dict, который вы передаете в представление (или в RequestContext). Это самый подход к Django-thnonic (?), Но это означает, что логика представления была отброшена назад в представления, которые мне не нравятся.

  • Используйте тег expr для установки значений в шаблонах нижнего уровня. Примечание: это работает только в том случае, если вы {% include%} шаблон, потому что он должен быть оценен до включения. Вы не можете сделать это с помощью {% extends%}, потому что это должно быть первым в дочернем шаблоне.

  • Переключитесь на Jinja2, по крайней мере, для просмотров, где вам нужно это сделать.

После того, как вы установили эти значения, вы можете делать такие вещи:

<div class="foo{% if foo_active%}_active{%endif%}"> stuff </div>

Это делает класс div "foo", когда он неактивен, и "foo_active", когда он есть. Стиль по вкусу, но не добавляйте слишком много корицы.: -)

Ответ 5

Я принял подход Jarret Hardie "low tech" в подобном, err... контексте (да, это каламбур... который не будет иметь для вас никакого смысла, если я не скажу вам, что я не занимался навигацией но установив цвет рамки кнопок, чтобы показать, какой из них был нажат).

Но моя версия немного компактнее, я думаю. Вместо того, чтобы определять только одну активную панель контекстной переменной в представлении, я возвращаю словарь, но всегда только с одной парой ключ-значение: например. activebar = {'foo': 'active'}.

Затем в шаблоне я просто пишу class= "{{activebar.foo}} в якоре foo и, соответственно, в других якорях. Если определено, что только activebar.foo имеет значение" active ", то activebar.bar в якоре бара ничего не сделает. Может быть," терпеть неудачу" - это правильная беседа с Django. И Боб твой дядя.

EDIT: Ой... прошло несколько дней, и хотя то, что я написал выше, работало для меня, проблема возникла, когда я ввел в навигатор якорь с новым окном в качестве цели. Это, по-видимому, было причиной странного сбоя: после нажатия на новое окно (вкладка в Firefox), а затем вернувшись к тому, с которого было запущено новое окно, части дисплея под навигационной панелью стали пустыми, когда я быстро перемещал курсор над элементами на навигационной панели --- не нажимая ни на что. Мне пришлось принудительно перерисовать экран, перемещая полосу прокрутки (не перезагружая страницу, хотя это слишком сработало, потому что оно связано с перерисовкой экрана).

Я слишком много нуба, чтобы понять, почему это может произойти. И возможно, что я сделал что-то еще, что вызвало проблему, которая каким-то образом ушла. Но... я нашел более простой подход, который отлично работает для меня. Мои обстоятельства заключаются в том, что каждый дочерний шаблон, который запускается из представления, должен приводить к тому, что связанный элемент навигатора должен отображаться как "активный". Действительно, этот элемент navbar - это тот, который запустил представление, которое запустило дочерний шаблон - обычное дело.

Мое решение --- давайте возьмем элемент навигации "login" в качестве примера --- это поместить его в дочерний шаблон, содержащий форму входа.

{% block login %}active{% endblock %}

Я поставил его ниже заголовка, но я не предполагаю, что это место имеет значение. Затем в родительском шаблоне, который содержит определение navbar, для тега li, который окружает якорь для элемента навигации navbar, я положил... ну вот код:

<li class="{% block login %}{% endblock %}"><a href="/mysite/login">Login</a></li>

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

Словарный подход, который я описал выше, заключался в том, чтобы показать, какая из кнопок кнопок была нажата, когда все они были на одном и том же дочернем шаблоне. Это все еще работает для меня, и поскольку задействован только один дочерний шаблон, я не вижу, как мой новый метод для navbars будет работать в этом случае. Обратите внимание, что при новом методе отображения navbars даже не задействованы. Simpler!

Ответ 6

К сожалению, я не могу найти чистый способ.

Закончено помещать тег в каждое приложение base.html:

<span class="main_nav_bar_hint" id="2"></span>

(На самом деле я использую два. Один набор из базы приложений для основного навигатора. Один набор страниц приложения для панели навигации приложения)

И немного магии JQuery в проекте base.html

$(document).ready(function() { $("#nav_menu_" + $(".main_nav_bar_hint").attr("id")).removeClass("normal").addClass("selected"); })

Его немного взломать, но таким образом его легко понять, и мне нужно только сделать логические изменения, добавив еще приложения.