49đ
Note: I provide the full snippet below, since djangosnippets has been finicky lately.
Cool, someone actually found my snippet đ The use of my template tag is rather simple.
To answer your question there is no âbuilt-inâ django mechanism for dealing with breadcrumbs, but it does provide us with the next best thing: custom template tags.
Imagine you want to have breadcrumbs like so:
Services -> Programming
Services -> Consulting
Then you will probably have a few named urls: âservicesâ, and âprogrammingâ, âconsultingâ:
(r'^services/$',
'core.views.services',
{},
'services'),
(r'^services/programming$',
'core.views.programming',
{},
'programming'),
(r'^services/consulting$',
'core.views.consulting',
{},
'consulting'),
Now inside your html template (lets just look at consulting page) all you have to put is:
//consulting.html
{% load breadcrumbs %}
{% block breadcrumbs %}
{% breadcrumb_url 'Services' services %}
{% breadcrumb_url 'Consulting' consulting %}
{% endblock %}
If you want to use some kind of custom text within the breadcrumb, and donât want to link it, you can use breadcrumb tag instead.
//consulting.html
{% load breadcrumbs %}
{% block breadcrumbs %}
{% breadcrumb_url 'Services' services %}
{% breadcrumb_url 'Consulting' consulting %}
{% breadcrumb 'We are great!' %}
{% endblock %}
There are more involved situations where you might want to include an id of a particular object, which is also easy to do. This is an example that is more realistic:
{% 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 breadcrumbs snippet
Provides two template tags to use in your HTML templates: breadcrumb and breadcrumb_url. The first allows creating of simple url, with the text portion and url portion. Or only unlinked text (as the last item in breadcrumb trail for example). The second, can actually take the named url with arguments! Additionally it takes a title as the first argument.
This is a templatetag file that should go into your /templatetags directory.
Just change the path of the image in the method create_crumb and you are good to go!
Donât forget to {% load breadcrumbs %} at the top of your html template!
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 %s" % (crumb, title)
return crumb
19đ
The Django admin view modules have automatic breadcumbs, which are implemented like this:
{% block breadcrumbs %}
<div class="breadcrumbs">
<a href="{% url 'admin:index' %}">{% trans 'Home' %}</a>
{% block crumbs %}
{% if title %} › {{ title }}{% endif %}
{% endblock %}
</div>
{% endblock %}
So there is some kind of built-in support for this..
- [Django]-How do I remove Label text in Django generated form?
- [Django]-HTTPError 403 (Forbidden) with Django and python-social-auth connecting to Google with OAuth2
- [Django]-How do I use CreateView with a ModelForm
9đ
My view functions emit the breadcrumbs as a simple list.
Some information is kept in the userâs session. Indirectly, however, it comes from the URLâs.
Breadcrumbs are not a simple linear list of where theyâve been â thatâs what browser history is for. A simple list of where theyâve been doesnât make a good breadcrumb trail because it doesnât reflect any meaning.
For most of our view functions, the navigation is pretty fixed, and based on template/view/URL design. In our cases, thereâs a lot of drilling into details, and the breadcrumbs reflect that narrowing â we have a ârealmâ, a âlistâ, a âparentâ and a âchildâ. They form a simple hierarchy from general to specific.
In most cases, a well-defined URL can be trivially broken into a nice trail of breadcrumbs. Indeed, thatâs one test for good URL design â the URL can be interpreted as breadcrumbs and displayed meaningfully to the users.
For a few view functions, where we present information thatâs part of a âmany-to-manyâ join, for example, there are two candidate parents. The URL may say one thing, but the sessionâs context stack says another.
For that reason, our view functions have to leave context clues in the session so we can emit breadcrumbs.
- [Django]-Django FileField: How to return filename only (in template)
- [Django]-How to resolve AssertionError: .accepted_renderer not set on Response in django and ajax
- [Django]-Django: best practice way to get model from an instance of that model
5đ
Try django-breadcrumbs â a pluggable middleware that add a breadcrumbs callable/iterable in your request object.
It supports simple views, generic views and Django FlatPages app.
- [Django]-Serializing a list of objects with django-rest-framework
- [Django]-TextField missing in django.forms
- [Django]-Retrieving parameters from a URL
5đ
I had the same issue and finally Iâve made simple django tempalate tag for it: https://github.com/prymitive/bootstrap-breadcrumbs
- [Django]-What is an efficient way of inserting thousands of records into an SQLite table using Django?
- [Django]-No handlers could be found for logger
- [Django]-Google Static Maps URL length limit
3đ
http://www.djangosnippets.org/snippets/1289/ â provides a template tag but iâm not sure this would work if you donât have your urls.py properly declared.
Nothing will work if you donât have your urls.py
properly declared. Having said that, it doesnât look as though it imports from urls.py
. In fact, it looks like to properly use that tag, you still have to pass the template some variables. Okay, thatâs not quite true: indirectly through the default url
tag, which the breadcrumb
tag calls. But as far as I can figure, it doesnât even actually call that tag; all occurrences of url
are locally created variables.
But Iâm no expert at parsing template tag definitions. So say somewhere else in the code it magically replicates the functionality of the url tag. The usage seems to be that you pass in arguments to a reverse lookup. Again, no matter what your project is, you urls.py
should be configured so that any view can be reached with a reverse lookup. This is especially true with breadcrumbs. Think about it:
home > accounts > my account
Should accounts, ever hold an arbitrary, hardcoded url? Could âmy accountâ ever hold an arbitrary, hardcoded url? Some way, somehow youâre going to write breadcrumbs in such a way that your urls.py
gets reversed. Thatâs really only going to happen in one of two places: in your view, with a call to reverse
, or in the template, with a call to a template tag that mimics the functionality of reverse
. There may be reasons to prefer the former over the latter (into which the linked snippet locks you), but avoiding a logical configuration of your urls.py
file is not one of them.
- [Django]-How to annotate Count with a condition in a Django queryset
- [Django]-Exclude a field from django rest framework serializer
- [Django]-Automatic creation date for Django model form objects
3đ
Try django-mptt.
Utilities for implementing Modified Preorder Tree Traversal (MPTT) with your Django Model classes and working with trees of Model instances.
- [Django]-How to break "for loop" after 1 iteration in Django template
- [Django]-ImproperlyConfigured: The included urlconf <project>.urls doesn't have any patterns in it
- [Django]-Django setUpTestData() vs. setUp()
3đ
This answer is just the same as @Andriy Drozdyuk (link). I just want to edit something so it works in Django 3.2 (in my case) and good in bootstrap too.
for create_crumb
function (Remove the ">" bug in the current code)
def create_crumb(title, url=None):
"""
Helper function
"""
if url:
crumb = '<li class="breadcrumb-item"><a href="{}">{}</a></li>'.format(url, title)
else:
crumb = '<li class="breadcrumb-item active" aria-current="page">{}</li>'.format(title)
return crumb
And for __init__
in BreadcrumbNode
, add list()
to make it subscriptable. And change smart_unicode
to smart_text
in render
method
from django.utils.encoding import smart_text
class BreadcrumbNode(Node):
def __init__(self, vars):
"""
First var is title, second var is url context variable
"""
self.vars = list(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_text(title)
And add this in base.html
for the view for Bootstrap. Check the docs
<nav style="--bs-breadcrumb-divider: '>';" aria-label="breadcrumb">
<ol class="breadcrumb">
{% block breadcrumbs %}
{% endblock breadcrumbs %}
</ol>
</nav>
- [Django]-What's the best way to start learning django?
- [Django]-Access Django model's fields using a string instead of dot syntax?
- [Django]-Are there any plans to officially support Django with IIS?
2đ
Obviously, no one best answer, but for practical reason I find that it is worth considering the naïve way. Just overwrite and rewrite the whole breadcrumb⊠(at least until the official django.contrib.breadcrumb
released )
Without being too fancy, it is better to keep things simple. It helps the newcomer to understand. It is extremely customizable (e.g. permission checking, breadcrumb icon, separator characters, active breadcrumb, etcâŠ)
Base Template
<!-- 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>
Implementation Template
Later on each pages we rewrite and overwrite the whole breadcrumb block.
<!-- 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 use cases:
- Django Oscar: base template, simple bread
- Django Admin: base template, simple bread, permission check breadcrumb
- [Django]-Sort order of Django Admin records
- [Django]-Allowing only super user login
- [Django]-How can I avoid "Using selector: EpollSelector" log message in Django?
1đ
You could also reduce the boiler plate required to manage breadcrumbs using django-view-breadcrumbs, by adding a crumbs property to the view.
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 %}
- [Django]-How to remove all of the data in a table using Django
- [Django]-Turn off automatic pagination of Django Rest Framework ModelViewSet
- [Django]-Django TemplateDoesNotExist?
0đ
Something like this may work for your situation:
Capture the entire URL in your view and make links from it. This will require modifying your urls.py, each view that needs to have breadcrumbs, and your templates.
First you would capture the entire URL in your urls.py file
original urls.py
...
(r'^myapp/$', 'myView'),
(r'^myapp/(?P<pk>.+)/$', 'myOtherView'),
...
new urls.py
...
(r'^(?P<whole_url>myapp/)$', 'myView'),
(r'^(?P<whole_url>myapp/(?P<pk>.+)/)$', 'myOtherView'),
...
Then in your view something like:
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)
...
Which should be pulled out into a function that gets imported into the views that need it
Then in your template print out the breadcrumbs
myTemplate.html
...
<div class="breadcrumb-nav">
<ul>
{% for breadcrumb in breadcrumbs %}
<li><a href="{{ breadcrumb.url }}">{{ breadcrumb.slug }}</a></li>
{% endfor %}
</ul>
</div>
...
One shortcoming of doing it this way is that as it stands you can only show the âdirectoryâ part of the url as the link text. One fix for this off the top of my head (probably not a good one) would be to keep a dictionary in the file that defines the breadcrumb function.
Anyways thatâs one way you could accomplish breadcrumbs, cheers đ
- [Django]-Limit foreign key choices in select in an inline form in admin
- [Django]-Django Rest Framework Token Authentication
- [Django]-Referencing multiple submit buttons in django
0đ
You might want to try django-headcrumbs (donât worry, they are not going to eat your brains).
Itâs very lightweight and absolutely straightforward to use, all you have to do is annotate your views (because defining crumbs structure in templates sounds crazy to me) with a decorator that explains how to get back from the given view.
Here is an example from the documentation:
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.
There are also some utility functions (e.g. name_from_pk
you can see in the example) that automagically generate nice names for your crumbs without you having to wright lots of code.
- [Django]-Django â "no module named django.core.management"
- [Django]-How can I get the object count for a model in Django's templates?
- [Django]-What does 'many = True' do in Django Rest FrameWork?
0đ
Iâve created template filter for this.
Apply your custom filter (Iâve named it âmakebreadcrumbsâ) to the request.path like this:
{% with request.resolver_match.namespace as name_space %}
{{ request.path|makebreadcrumbs:name_space|safe }}
{% endwith %}
We need to pass url namespace as an arg to our filter.
Also use safe filter, because our filter will be returning string that needs to be resolved as html content.
Custom filter should look like this:
@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 ' > '.join(my_crumbs)
# return whole list of crumbs joined by the right arrow special character.
Important:
splited parts of the âvalueâ in our filter should be equal to the namespace in the urls.py, so the reverse method can be called.
Hope it helped.
- [Django]-Chained method calls indentation style in Python
- [Django]-Why is Django throwing error "DisallowedHost at /"?
- [Django]-How to access request body when using Django Rest Framework and avoid getting RawPostDataException
0đ
A generic way, to collect all callable paths of the current url could be resolved by the following code snippet:
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}
If the resolve
function canât get a real path from any urlpattern, the Resolver404
exception will be thrown. For those items we set the is_representative
flag to false. The OrderedDict
breadcrumb_config
holds after that the breadcrumb items with there configuration.
For bootstrap 4 breadcrumb for example, you can do something like the following in your template:
<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>
Only the links which wonât raises a 404
are clickable.
- [Django]-Define css class in django Forms
- [Django]-How to run Django's test database only in memory?
- [Django]-What's the idiomatic Python equivalent to Django's 'regroup' template tag?
0đ
I believe there is nothing simpler than that (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;
}
- [Django]-Django print choices value
- [Django]-Custom QuerySet and Manager without breaking DRY?
- [Django]-How to TRUNCATE TABLE using Django's ORM?