47

「Djangoブレッドクラム」のGoogle検索を実行する際に提供されるいくつかのソリューションには、テンプレートと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メソッドを使用するバリエーションを使用しました。

それなら、これは主観的な質問ではありません。

4

14 に答える 14

46

注:djangosnippetsは最近気難しいので、以下に完全なスニペットを提供します。

かっこいい、誰かが実際に私のスニペットを見つけました:-)私のテンプレートタグの使用はかなり簡単です。

あなたの質問に答えるために、ブレッドクラムを処理するための「組み込みの」djangoメカニズムはありませんが、次善の策であるカスタムテンプレートタグを提供します。

次のようなパンくずリストが必要だとします。

Services -> Programming
Services -> Consulting

次に、「services」、「programming」、「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 %}

特定のオブジェクトのIDを含めたい場合は、もっと複雑な状況がありますが、これも簡単です。これは、より現実的な例です。

{% 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テンプレートで使用する2つのテンプレートタグ、breadcrumbとbreadcrumb_urlを提供します。1つ目は、テキスト部分とurl部分を含む単純なURLの作成を可能にします。または、リンクされていないテキストのみ(たとえば、ブレッドクラムトレイルの最後のアイテムとして)。2つ目は、引数付きの名前付きURLを実際に取得できます。さらに、最初の引数としてタイトルを取ります。

これは、/templatetagsディレクトリに配置する必要があるtemplatetagファイルです。

create_crumbメソッドで画像のパスを変更するだけで、準備完了です。

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
于 2009-05-06T18:56:55.297 に答える
15

Django管理ビューモジュールには自動ブレッドカンブがあり、次のように実装されています

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

したがって、これにはある種の組み込みサポートがあります。

于 2012-01-16T11:14:58.770 に答える
7

私のビュー関数は、ブレッドクラムを単純なリストとして出力します。

一部の情報はユーザーのセッションに保持されます。ただし、間接的にはURLから取得されます。

ブレッドクラムは、それらがどこにあったかを示す単純な線形リストではありません。これが、ブラウザの履歴の目的です。それらがどこにあったかという単純なリストは、意味を反映していないため、適切なパンくずリストにはなりません。

ほとんどのビュー機能では、ナビゲーションはかなり固定されており、テンプレート/ビュー/URLの設計に基づいています。私たちの場合、詳細を掘り下げることがたくさんあり、ブレッドクラムはその狭まりを反映しています。「レルム」、「リスト」、「親」、「子」があります。それらは、一般的なものから特定のものまでの単純な階層を形成します。

ほとんどの場合、明確に定義されたURLは、ブレッドクラムのすばらしい軌跡に簡単に分割できます。確かに、これは優れたURL設計の1つのテストです。つまり、URLはブレッドクラムとして解釈され、ユーザーにとって意味のある形で表示されます。

たとえば、「多対多」結合の一部である情報を提示するいくつかのビュー関数の場合、2つの候補の親があります。URLは1つのことを言っているかもしれませんが、セッションのコンテキストスタックは別のことを言っています。

そのため、ビュー関数はセッションにコンテキストの手がかりを残して、ブレッドクラムを発行できるようにする必要があります。

于 2009-05-05T21:16:25.800 に答える
5

django-breadcrumbs —リクエストオブジェクトに呼び出し可能/反復可能なブレッドクラムを追加するプラグ可能なミドルウェアを試してください。

シンプルなビュー、一般的なビュー、DjangoFlatPagesアプリをサポートしています。

于 2010-02-25T16:31:21.227 に答える
5

同じ問題が発生し、最終的に単純なdjango tempalateタグを作成しました:https ://github.com/prymitive/bootstrap-breadcrumbs

于 2012-10-04T13:15:49.047 に答える
3

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が逆転するような方法でパンくずを書くつもりです。これは、実際には2つの場所のいずれかでのみ発生します。ビュー内で、への呼び出しを使用するreverseか、テンプレート内で、の機能を模倣するテンプレートタグへの呼び出しを使用しますreverse。後者(リンクされたスニペットがロックされる)よりも前者を好む理由があるかもしれませんが、urls.pyファイルの論理構成を回避することはそれらの1つではありません。

于 2009-05-05T21:46:09.097 に答える
3

django-mpttを試してください。

DjangoModelクラスでModifiedPreorderTree Traversal(MPTT)を実装し、Modelインスタンスのツリーを操作するためのユーティリティ。

于 2009-07-18T09:12:49.013 に答える
2

明らかに、誰も最良の答えはありませんが、実際的な理由から、素朴な方法を検討する価値があると思います。ブレッドクラム全体を上書きして書き直すだけです...(少なくとも公式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 %}

実用性

実際のユースケース:

于 2016-09-21T08:02:56.140 に答える
1

ビューにクラムプロパティを追加することで、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 %}
于 2018-12-12T16:10:50.533 に答える
0

このようなものがあなたの状況に役立つかもしれません:

ビュー内のURL全体をキャプチャし、そこからリンクを作成します。これには、urls.py、ブレッドクラムが必要な各ビュー、およびテンプレートを変更する必要があります。

まず、urls.pyファイルにURL全体をキャプチャします

元の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>
...

この方法の欠点の1つは、現状では、URLの「ディレクトリ」部分のみをリンクテキストとして表示できることです。これに対する私の頭のてっぺんからの1つの修正(おそらく良いものではない)は、ブレッドクラム関数を定義するファイルに辞書を保持することです。

とにかく、それはあなたがパンくずを達成することができる1つの方法です、乾杯:)

于 2009-05-05T23:00:58.777 に答える
0

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たくさんのコードを書かなくても、パン粉の素敵な名前を自動的に生成するユーティリティ関数もいくつかあります(例で確認できます)。

于 2013-03-06T09:44:17.300 に答える
0

このためのテンプレートフィルターを作成しました。

次のように、カスタムフィルター(「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.

重要:

フィルタの「value」の分割された部分は、urls.pyの名前空間と同じである必要があるため、reverseメソッドを呼び出すことができます。

お役に立てば幸いです。

于 2016-01-11T16:58:25.120 に答える
0

現在のURLの呼び出し可能なパスをすべて収集する一般的な方法は、次のコードスニペットで解決できます。

from django.urls import resolve, Resolver404

path_items = request.path.split("/")
path_items.pop(0)
path_tmp = ""

breadcrumb_config = OrderedDict()
for path_item in path_items:
    path_tmp += "/" + path_item
    try:
        resolve(path_tmp)
        breadcrumb_config[path_item] = {'is_representative': True, 'current_path': path_tmp}
    except Resolver404:
        breadcrumb_config[path_item] = {'is_representative': False, 'current_path': path_tmp}

resolve関数がどのurlpatternからも実際のパスを取得できない場合、例外Resolver404がスローされます。これらのアイテムについては、is_representativeフラグをfalseに設定します。その後OrderedDict breadcrumb_config、そこに構成されたブレッドクラムアイテムが保持されます。

たとえば、ブートストラップ4ブレッドクラムの場合、テンプレートで次のようなことを行うことができます。

<nav aria-label="breadcrumb">
  <ol class="breadcrumb">
      {% for crumb, values in BREADCRUMB_CONFIG.items %}
        <li class="breadcrumb-item {% if forloop.last or not values.is_representative %}active{% endif %}" {% if forloop.last %}aria-current="page"{% endif %}>
            {% if values.is_representative %}
                <a href="{{values.current_path}}">
                    {{crumb}}
                </a>
            {% else %}
                {{crumb}}
            {% endif %}
        </li>
      {% endfor %}
  </ol>
</nav>

を発生させないリンクのみ404がクリック可能です。

于 2021-02-02T12:51:16.597 に答える
0

それよりも簡単なものはないと思います(django 3.2):

 def list(request):
        return render(request, 'list.html', {
            'crumbs' : [
                ("Today", "https://www.python.org/"),
                ("Is", "https://www.python.org/"),
                ("Sunday", "https://www.djangoproject.com/"),
            ]
        })

Breadcrumbs.html

<div class="page-title-right">
   <ol class="breadcrumb m-0">
      {% if crumbs %}
            {% for c in crumbs %}
                <li class="breadcrumb-item {{c.2}}"><a href="{{c.1}}">{{c.0}}</a></li>
            {% endfor %}
      {% endif %}
   </ol>
</div>

css:

.m-0 {
    margin: 0!important;
}
.breadcrumb {
    display: flex;
    flex-wrap: wrap;
    padding: 0 0;
    margin-bottom: 1rem;
    list-style: none;
    border-radius: .25rem;
}
dl, ol, ul {
    margin-top: 0;
    margin-bottom: 1rem;
}
ol, ul {
    padding-left: 2rem;
}

ここに画像の説明を入力してください

于 2021-08-15T09:58:14.277 に答える