Skip to content

Commit

Permalink
Merge 4e9803c into ff13293
Browse files Browse the repository at this point in the history
  • Loading branch information
jbeyers committed Dec 14, 2016
2 parents ff13293 + 4e9803c commit 4a107a0
Show file tree
Hide file tree
Showing 4 changed files with 163 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{% load navbuilder_tags %}
{% for crumb in navbuilder_breadcrumbs %}
<a class="Crumb" href="{{ crumb.link.get_absolute_url }}" title="{{ crumb.link.title|default:crumb.title }}" target="{{ crumb.target|default:"" }}" data-slug="{{ crumb.link.slug|default:crumb.slug }}">{{ crumb.link.title|default:crumb.title }}</a>
{% if not forloop.last %} > {% endif %}
{% endfor %}
48 changes: 47 additions & 1 deletion navbuilder/templatetags/navbuilder_tags.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from django import template
from django.contrib.contenttypes.models import ContentType

from navbuilder.models import Menu
from navbuilder.models import Menu, MenuItem

register = template.Library()

Expand All @@ -22,3 +23,48 @@ def render_menu(context, slug):
def render_menuitem(context, obj):
context["object"] = obj
return context


@register.inclusion_tag(
"navbuilder/inclusion_tags/breadcrumbs.html", takes_context=True
)
def navbuilder_breadcrumbs(context, slug):
"""
Render the breadcrumbs, based on the current object. Prefer using the
structure of the menu designated by slug, but use any menu available.
Typical use case for this would be if the main menu has an about/terms
page, but it's mirrored in the footer menu in a much flatter layout. We
prefer the main menu structure. This also allows us to construct
breadcrumbs for items that don't show up in page menus at all.
"""
context["navbuilder_breadcrumbs"] = []
if "object" not in context:
return context

def get_menuitems(item):
if item.parent:
struct = get_menuitems(item.parent)
struct.append(item)
return struct
return [item]

content_type = ContentType.objects.get_for_model(context["object"])
crumb_sets = []
for item in MenuItem.objects.filter(
link_content_type__pk=content_type.id,
link_object_id = context["object"].id):

crumb_sets.append(get_menuitems(item))

for crumb_set in crumb_sets:
menu = crumb_set[0].menu
if menu and menu.slug == slug:
context["navbuilder_breadcrumbs"] = crumb_set

if not context["navbuilder_breadcrumbs"]:
if crumb_sets:
context["navbuilder_breadcrumbs"] = crumb_sets[0]
else:
context["navbuilder_breadcrumbs"] = []

return context
36 changes: 36 additions & 0 deletions navbuilder/tests/test_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,39 @@ def load_fixtures(kls):
kls.sub_menuitem = models.MenuItem.objects.create(
**kls.sub_menuitem_data
)


def load_crumb_fixtures(kls):
kls.menu_data_2 = {
"title": "Menu 2",
"slug": "menu-2"
}
kls.menu_2 = models.Menu.objects.create(**kls.menu_data_2)

kls.link_data_2 = {
"title": "Link 2",
"slug": "link-2",
"url": "/link/2/"
}
kls.link_2 = Link.objects.create(**kls.link_data_2)

kls.menuitem_data_2 = {
"title": "Menu Item 2",
"slug": "menu-item-2",
"position": 2,
"menu": kls.menu_2,
"link": kls.link
}
kls.menuitem_2 = models.MenuItem.objects.create(**kls.menuitem_data_2)

kls.sub_menuitem_data_2 = {
"title": "Sub Menu Item 2",
"slug": "sub-menu-item-2",
"position": 2,
"parent": kls.menuitem_2,
"target": "blank",
"link": None
}
kls.sub_menuitem_2 = models.MenuItem.objects.create(
**kls.sub_menuitem_data_2
)
75 changes: 75 additions & 0 deletions navbuilder/tests/test_breadcrumbs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from django.core.urlresolvers import reverse
from django.test import TestCase
from django.test.client import Client

from navbuilder import models
from navbuilder.tests.test_base import load_fixtures, load_crumb_fixtures

from django.template import Context, Template

crumb_template_1 = Template(
"{% load navbuilder_tags %}"
"{% navbuilder_breadcrumbs 'menu-1' %}"
)

crumb_template_2 = Template(
"{% load navbuilder_tags %}"
"{% navbuilder_breadcrumbs 'menu-2' %}"
)

crumb_template_3 = Template(
"{% load navbuilder_tags %}"
"{% navbuilder_breadcrumbs 'menu-3' %}"
)


class BreadcrumbsTestCase(TestCase):
def setUp(self):
self.client = Client()
load_fixtures(self)
load_crumb_fixtures(self)
# Reorganise the items
self.menuitem.link = None
self.sub_menuitem_2.link = self.link


def test_single_level(self):
# The link object maps to a single level in menu 2
out = crumb_template_2.render(Context({"object": self.link}))
self.assertHTMLEqual(out, """
<a class="Crumb" href="/link/1/" title="Link 1"
target="" data-slug="link-1">
Link 1
</a>
"""
)

def test_multilevel(self):
# The link object maps to the submenu in menu 1
out = crumb_template_1.render(Context({"object": self.link}))
self.assertHTMLEqual(out, """
<a class="Crumb" href="/link/1/"
title="Link 1" target="" data-slug="link-1">
Link 1
</a>
>
<a class="Crumb" data-slug="link-1" href="/link/1/"
target="blank" title="Link 1">
Link 1
</a>
"""
)

def test_menu_slug_not_found(self):
# If we cannot identify the menu it comes from, take the first one.
out = crumb_template_3.render(Context({"object": self.link}))
self.assertIn("Link 1", out)

def test_no_matching_menuitem(self):
# If the object does not show up in any menu, render nothing
self.menuitem_2.link = None
out = crumb_template_3.render(Context({"object": self.link_2}))
self.assertHTMLEqual("", out)

def tearDown(self):
pass

0 comments on commit 4a107a0

Please sign in to comment.