Как реализовать панировочные сухари в шаблоне Django? - PullRequest
39 голосов
/ 06 мая 2009

Некоторые решения, предоставляемые для поиска в Google «хлебных крошек Django», включают использование шаблонов и block.super, в основном просто расширение базовых блоков и добавление к ним текущей страницы. http://www.martin -geber.com / мысль / 2007/10/25 / панировочные сухари-Джанго-шаблоны /

http://www.djangosnippets.org/snippets/1289/ - предоставляет тег шаблона, но я не уверен, что это сработает, если у вас не будет должным образом объявлен ваш urls.py.

Мне интересно, как лучше? И если вы уже реализовали панировочные сухари, как вы это делали?

--- Редактировать -

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

Полагаю, это слишком субъективный вопрос.

Ответы [ 12 ]

43 голосов
/ 06 мая 2009

Примечание. Ниже приведен полный фрагмент кода, поскольку в последнее время djangosnippets был привередливым.

Круто, кто-то действительно нашел мой фрагмент :-) Использование моего тега шаблона довольно просто.

Чтобы ответить на ваш вопрос, не существует «встроенного» механизма django для работы с панировочными сухарями, но он предоставляет нам следующую лучшую вещь: пользовательские теги шаблонов.

Представьте, что вы хотите, чтобы хлебные крошки были такими:

Services -> Programming
Services -> Consulting

Тогда у вас, вероятно, будет несколько названных URL-адресов: "услуги" и "программирование", "консалтинг":

    (r'^services/$',
     'core.views.services',
     {},
     'services'),

    (r'^services/programming$',
     'core.views.programming',
     {},
     'programming'),

    (r'^services/consulting$',
     'core.views.consulting',
     {},
     'consulting'),

Теперь внутри вашего html-шаблона (давайте просто посмотрим на консультационную страницу) все, что вам нужно, это:

//consulting.html
{% load breadcrumbs %}

{% block breadcrumbs %}
{% breadcrumb_url 'Services' services %}
{% breadcrumb_url 'Consulting' consulting %}

{% endblock %}

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

//consulting.html
{% load breadcrumbs %}

{% block breadcrumbs %}
  {% breadcrumb_url 'Services' services %}
  {% breadcrumb_url 'Consulting' consulting %}
  {% breadcrumb 'We are great!' %}  
{% endblock %}

Есть более сложные ситуации, когда вы можете захотеть включить идентификатор определенного объекта, что также легко сделать. Это более реалистичный пример:

{% load breadcrumbs %}

{% block breadcrumbs %}
{% breadcrumb_url 'Employees' employee_list %}
{% if employee.id %}
    {% breadcrumb_url employee.company.name company_detail employee.company.id %}
    {% breadcrumb_url employee.full_name employee_detail employee.id %}
    {% breadcrumb 'Edit Employee ' %}
{% else %}
    {% breadcrumb 'New Employee' %}
{% endif %}

{% endblock %}

фрагмент крошки DaGood

Предоставляет два тега шаблона для использования в шаблонах HTML: breadcrumb и breadcrumb_url. Первый позволяет создать простой URL, с текстовой частью и частью URL. Или только несвязанный текст (например, последний элемент в журнале). Во-вторых, может фактически взять названный URL с аргументами! Кроме того, в качестве первого аргумента используется заголовок.

Это файл тега шаблона, который должен находиться в каталоге / templatetags.

Просто измените путь к изображению в методе create_crumb и все готово!

Не забудьте {% load breadcrumbs%} вверху вашего HTML-шаблона!

from django import template
from django.template import loader, Node, Variable
from django.utils.encoding import smart_str, smart_unicode
from django.template.defaulttags import url
from django.template import VariableDoesNotExist

register = template.Library()

@register.tag
def breadcrumb(parser, token):
    """
    Renders the breadcrumb.
    Examples:
        {% breadcrumb "Title of breadcrumb" url_var %}
        {% breadcrumb context_var  url_var %}
        {% breadcrumb "Just the title" %}
        {% breadcrumb just_context_var %}

    Parameters:
    -First parameter is the title of the crumb,
    -Second (optional) parameter is the url variable to link to, produced by url tag, i.e.:
        {% url person_detail object.id as person_url %}
        then:
        {% breadcrumb person.name person_url %}

    @author Andriy Drozdyuk
    """
    return BreadcrumbNode(token.split_contents()[1:])


@register.tag
def breadcrumb_url(parser, token):
    """
    Same as breadcrumb
    but instead of url context variable takes in all the
    arguments URL tag takes.
        {% breadcrumb "Title of breadcrumb" person_detail person.id %}
        {% breadcrumb person.name person_detail person.id %}
    """

    bits = token.split_contents()
    if len(bits)==2:
        return breadcrumb(parser, token)

    # Extract our extra title parameter
    title = bits.pop(1)
    token.contents = ' '.join(bits)

    url_node = url(parser, token)

    return UrlBreadcrumbNode(title, url_node)


class BreadcrumbNode(Node):
    def __init__(self, vars):
        """
        First var is title, second var is url context variable
        """
        self.vars = map(Variable,vars)

    def render(self, context):
        title = self.vars[0].var

        if title.find("'")==-1 and title.find('"')==-1:
            try:
                val = self.vars[0]
                title = val.resolve(context)
            except:
                title = ''

        else:
            title=title.strip("'").strip('"')
            title=smart_unicode(title)

        url = None

        if len(self.vars)>1:
            val = self.vars[1]
            try:
                url = val.resolve(context)
            except VariableDoesNotExist:
                print 'URL does not exist', val
                url = None

        return create_crumb(title, url)


class UrlBreadcrumbNode(Node):
    def __init__(self, title, url_node):
        self.title = Variable(title)
        self.url_node = url_node

    def render(self, context):
        title = self.title.var

        if title.find("'")==-1 and title.find('"')==-1:
            try:
                val = self.title
                title = val.resolve(context)
            except:
                title = ''
        else:
            title=title.strip("'").strip('"')
            title=smart_unicode(title)

        url = self.url_node.render(context)
        return create_crumb(title, url)


def create_crumb(title, url=None):
    """
    Helper function
    """
    crumb = """<span class="breadcrumbs-arrow">""" \
            """<img src="/media/images/arrow.gif" alt="Arrow">""" \
            """</span>"""
    if url:
        crumb = "%s<a href='%s'>%s</a>" % (crumb, url, title)
    else:
        crumb = "%s&nbsp;&nbsp;%s" % (crumb, title)

    return crumb
12 голосов
/ 16 января 2012

Модуль просмотра администратора Django имеет автоматические контрольные точки, которые реализованы следующим образом:

{% block breadcrumbs %}
    <div class="breadcrumbs">
        <a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
        {% block crumbs %}
            {% if title %} &rsaquo; {{ title }}{% endif %}
        {% endblock %}
    </div>
{% endblock %}

Так что есть какая-то встроенная поддержка для этого ..

6 голосов
/ 06 мая 2009

Мои функции просмотра генерируют хлебные крошки в виде простого списка.

Некоторая информация хранится в сеансе пользователя. Однако косвенным образом это происходит от URL.

Хлебные крошки - это не простой линейный список того, где они были - для этого существует история браузера. Простой список того, где они были, не является хорошим следом крошки, потому что он не отражает никакого смысла.

Для большинства наших функций просмотра навигация довольно фиксирована и основана на дизайне шаблона / представления / URL. В наших случаях много подробностей, и хлебные крошки отражают это сужение - у нас есть «область», «список», «родитель» и «ребенок». Они образуют простую иерархию от общего к конкретному.

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

Для нескольких функций просмотра, где мы представляем информацию, которая является частью объединения «многие ко многим», например, есть два кандидата в родители. URL может сказать одно, а стек контекста сеанса говорит другое.

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

5 голосов
/ 04 октября 2012

У меня была та же проблема, и, наконец, я сделал для нее простой шаблонный тег django: https://github.com/prymitive/bootstrap-breadcrumbs

5 голосов
/ 25 февраля 2010

Попробуйте django-breadcrumbs - сменное промежуточное ПО, которое добавляет крошки, вызываемые / повторяемые в вашем объекте запроса.

Он поддерживает простые представления, общие представления и приложение Django FlatPages.

3 голосов
/ 18 июля 2009

Попробуйте django-mptt .

Утилиты для реализации Модифицированного обхода дерева предзаказов (MPTT) с вашими классами Django Model и работы с деревьями экземпляров Model.

3 голосов
/ 06 мая 2009

http://www.djangosnippets.org/snippets/1289/ - предоставляет тег шаблона, но я не уверен, что это сработает, если у вас не будет должным образом объявлен ваш urls.py.

Ничто не сработает, если у вас нет urls.py, правильно объявленного. Сказав это, он не выглядит так, как будто он импортирует из urls.py. На самом деле, похоже, что для правильного использования этого тега вы все равно должны передать шаблону некоторые переменные. Ладно, это не совсем так: косвенно через тег url по умолчанию, который вызывает тег breadcrumb. Но, насколько я понимаю, он даже не вызывает этот тег; все вхождения url являются локально созданными переменными.

Но я не эксперт в разборе определений тегов шаблонов. Так скажем, где-то еще в коде это волшебным образом повторяет функциональность тега url. Похоже, вы используете аргументы для обратного поиска. Опять же, независимо от того, какой у вас проект, вы должны настроить urls.py так, чтобы к любому представлению можно было обратиться с помощью обратного просмотра. Это особенно верно с панировочными сухарями. Подумайте об этом:

home > accounts > my account

Должны ли учетные записи, когда-либо содержать произвольный, жестко запрограммированный URL? Может ли"мой аккаунт" содержать произвольный, жестко запрограммированный URL? Каким-то образом, так или иначе, вы собираетесь писать панировочные сухари так, чтобы ваш urls.py перевернулся. Это действительно произойдет только в одном из двух мест: с вашей точки зрения, с вызовом reverse или в шаблоне, с вызовом тега шаблона, который имитирует функциональность reverse. Могут быть причины, по которым предпочтение отдается первому, а не второму (в котором связанный фрагмент кода блокирует вас), но избегание логической конфигурации файла urls.py не является одним из них.

1 голос
/ 21 сентября 2016

Очевидно, что нет лучшего ответа, но по практическим соображениям я считаю, что стоит рассмотреть наивный путь. Просто переписать и переписать весь хлебный крошек ... (по крайней мере, до официального выпуска django.contrib.breadcrumb)

Не слишком прихотлив, лучше не усложнять. Это помогает новичку понять. Это чрезвычайно настраиваемый (например, проверка прав доступа , значок хлебных крошек , символов-разделителей , активные хлебные крошки и т. Д.)

Базовый шаблон

<!-- File: base.html -->
<html>
<body>
  {% block breadcrumb %}
  <ul class="breadcrumb">
    <li><a href="{% url 'dashboard:index' %}">Dashboard</a></li>
  </ul>
  {% endblock breadcrumb %}
  {% block content %}{% endblock content %}
</body>
</html>

Шаблон реализации

Позже на каждой странице мы перезаписываем и перезаписываем весь блок хлебных крошек.

<!-- File: page.html -->
{% extends 'base.html' %}
{% block breadcrumb %}
<ul class="breadcrumb">
  <li><a href="{% url 'dashboard:index' %}">Dashboard</a></li>
  <li><a href="{% url 'dashboard:level-1:index' %}">Level 1</a></li>
  <li class="active">Level 2</li>
</ul>
{% endblock breadcrumb %}

Practicallity

Примеры использования в реальном мире:

0 голосов
/ 12 декабря 2018

Вы также можете уменьшить плиту котла, необходимую для управления панировочными сухарями, используя django-view-breadcrumbs , добавив в представление свойство крошек.

urls.py

urlpatterns = [
    ...
    path('posts/<slug:slug>', views.PostDetail.as_view(), name='post_detail'),
    ...
] 

views.py

from django.views.generic import DetailView
from view_breadcrumbs import DetailBreadcrumbMixin


class PostDetail(DetailBreadcrumbMixin, DetailView):
    model = Post
    template_name = 'app/post/detail.html'

base.html

{% load django_bootstrap_breadcrumbs %}

{% block breadcrumbs %}
    {% render_breadcrumbs %}
{% endblock %}
0 голосов
/ 11 января 2016

Я создал шаблонный фильтр для этого.

Примените ваш пользовательский фильтр (я назвал его «makebreadcrumbs») к request.path так:

{% with request.resolver_match.namespace as name_space %}
    {{ request.path|makebreadcrumbs:name_space|safe }}
{% endwith %}

Нам нужно передать пространство имен url в качестве аргумента нашему фильтру.

Также используйте безопасный фильтр, потому что наш фильтр будет возвращать строку, которая должна быть разрешена как HTML-контент.

Пользовательский фильтр должен выглядеть следующим образом:

@register.filter
def makebreadcrumbs(value, arg):
    my_crumbs = []
    crumbs = value.split('/')[1:-1]  # slice domain and last empty value
    for index, c in enumerate(crumbs):
        if c == arg and len(crumbs) != 1:  
        # check it is a index of the app. example: /users/user/change_password - /users/ is the index.
            link = '<a href="{}">{}</a>'.format(reverse(c+':index'), c)
        else:
            if index == len(crumbs)-1:
                link = '<span>{}</span>'.format(c)  
                # the current bread crumb should not be a link.
            else:
                link = '<a href="{}">{}</a>'.format(reverse(arg+':' + c), c)
        my_crumbs.append(link)
    return ' &gt; '.join(my_crumbs)  
    # return whole list of crumbs joined by the right arrow special character.

Важно:

разделенные части 'значения' в нашем фильтре должны быть равны пространству имен в urls.py, поэтому можно вызвать обратный метод.

Надеюсь, это помогло.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...