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

Как реализовать панировочные сухари в шаблоне Django?

В некоторых решениях, связанных с поиском Google для "Django breadcrumbs", можно использовать шаблоны и block.super, в основном просто расширяя базовые блоки и добавляя к ним текущую страницу. http://www.martin-geber.com/thought/2007/10/25/breadcrumbs-django-templates/

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

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

--- Изменить -

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

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

4b9b3361

Ответ 1

Примечание. Ниже приведен полный фрагмент кода, поскольку в последнее время 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 %}

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

//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

Ответ 2

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

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

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

Ответ 3

Мои функции представления испускают панировочные сухари как простой список.

Некоторая информация хранится в сеансе пользователя. Косвенно, однако, он исходит из URL-адреса.

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

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

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

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

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

Ответ 4

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

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

Ответ 6

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

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

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

home > accounts > my account

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

Ответ 7

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

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

Ответ 8

Очевидно, что нет лучшего ответа, но по практическим соображениям я считаю, что стоит рассмотреть наивный способ. Просто перезапишите и перепишите всю сводку... (по крайней мере, до официального выпуска 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

Случаи использования Realworld:

Ответ 9

Что-то вроде этого может работать для вашей ситуации:

Захватите весь URL-адрес в своем представлении и сделайте ссылки на него. Это потребует изменения вашего urls.py, каждого представления, которое должно иметь панировочные сухари и ваши шаблоны.

Сначала вы захватили бы весь URL-адрес в файле urls.py

Оригинал urls.py
...
(r'^myapp/$', 'myView'),
(r'^myapp/(?P<pk>.+)/$', 'myOtherView'),
...
новый urls.py
...
(r'^(?P<whole_url>myapp/)$', 'myView'),
(r'^(?P<whole_url>myapp/(?P<pk>.+)/)$', 'myOtherView'),
...

Тогда в вашем представлении что-то вроде:

views.py
...
def myView(request, whole_url):
    # dissect the url
    slugs = whole_url.split('/')
    # for each 'directory' in the url create a piece of bread
    breadcrumbs = []
    url = '/'
    for slug in slugs:
        if slug != '':
            url = '%s%s/' % (url, slug)
            breadcrumb = { 'slug':slug, 'url':url }
            breadcrumbs.append(breadcrumb)

    objects = {
        'breadcrumbs': breadcrumbs,
    }
    return render_to_response('myTemplate.html', objects)
...

Который следует вытащить в функцию, которая импортируется в представления, которые в ней нуждаются

Затем в вашем шаблоне распечатайте панировочные сухари

myTemplate.html
...
<div class="breadcrumb-nav">
    <ul>
    {% for breadcrumb in breadcrumbs %}
        <li><a href="{{ breadcrumb.url }}">{{ breadcrumb.slug }}</a></li>
    {% endfor %}
    </ul>
</div>
...

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

В любом случае, один способ, которым вы могли бы сделать панировочные сухари, приветствия:)

Ответ 10

Возможно, вы захотите попробовать django-headcrumbs (не волнуйтесь, они не собираются есть ваши мозги).

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

Вот пример из документации:

from headcrumbs.decorators import crumb
from headcrumbs.util import name_from_pk

@crumb('Staff')  # This is the root crumb -- it doesn’t have a parent
def index(request):
    # In our example you’ll fetch the list of divisions (from a database)
    # and output it.

@crumb(name_from_pk(Division), parent=index)
def division(request, slug):
    # Here you find all employees from the given division
    # and list them.

Есть также некоторые служебные функции (например, name_from_pk, которые вы можете увидеть в примере), которые автоматически генерируют приятные имена для ваших крошек, не вызывая большого количества кода.

Ответ 11

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

Примените свой настраиваемый фильтр (я назвал его "makebreadcrumbs" ) на request.path следующим образом:

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

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

Также используйте безопасный фильтр, потому что наш фильтр будет возвращать строку, которая должна быть разрешена как содержимое 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, поэтому можно вызвать обратный метод.

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

Ответ 12

Вы также можете уменьшить размер плиты, необходимой для управления панировочными сухарями, используя 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 %}