Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement related views #23

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion AUTHORS.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ Val Kneeman under the name [django-menuware](https://github.com/un33k/django-men
* Milton Lenis - [email protected]

## Contributors:
* Jonathan Weth - [email protected]
* Jonathan Weth - [email protected]
* Dominik George - [email protected]
2 changes: 2 additions & 0 deletions docs/authors.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,5 @@ Contributors
============

`Jonathan Weth <https://github.com/hansegucker>`__ - [email protected]

`Dominik George <https://www.openhub.net/accounts/Natureshadow>`__ - [email protected]
5 changes: 4 additions & 1 deletion docs/menugeneration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ Django Menu Generator uses python dictionaries to represent the menu items, usua
"url": URL spec,
"root": True | False,
"related_urls": [ list of related URLs ],
"related_views": [ list of related views ],
"validators": [ list of validators ],
"submenu": Dictionary like this
}
Expand All @@ -25,6 +26,8 @@ Where each key is as follows:

- ``related_urls``: If one of this URLs is part of the path on the currently opened page, the menu item will be marked as selected (format of URLs like described at :doc:`urls`)

- ``related_views``: If the currently opened page resolves to one of these views, the menu item will be marked as selected.

- ``root``: A flag to indicate this item is the root of a path, with this you can correctly mark nested menus as selected.

- ``validators``: See :doc:`validators`
Expand Down Expand Up @@ -89,4 +92,4 @@ With this feature you can have a project structure like this::
...

You can have a mix of the two approaches if you wish
You can have a mix of the two approaches if you wish
15 changes: 13 additions & 2 deletions menu_generator/menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
from .utils import get_callable, parse_url

if django.VERSION >= (1, 10): # pragma: no cover
from django.urls import reverse, NoReverseMatch
from django.urls import resolve, reverse, NoReverseMatch
else:
from django.core.urlresolvers import reverse, NoReverseMatch
from django.core.urlresolvers import resolve, reverse, NoReverseMatch


class MenuBase(object):
Expand Down Expand Up @@ -83,12 +83,20 @@ def _get_related_urls(self, item_dict):
related_urls = item_dict.get('related_urls', [])
return [parse_url(url) for url in related_urls]

def _get_related_views(self, item_dict):
"""
Given a menu item dictionary, it returns the relateds viewss or an empty list.
"""
related_views = item_dict.get('related_views', [])
return related_views

def _is_selected(self, item_dict):
"""
Given a menu item dictionary, it returns true if `url` is on path,
unless the item is marked as a root, in which case returns true if `url` is part of path.

If related URLS are given, it also returns true if one of the related URLS is part of path.
If related views are given, it also returns true if the path maps to one of these views.
"""
url = self._get_url(item_dict)
if self._is_root(item_dict) and url in self.path:
Expand All @@ -100,6 +108,9 @@ def _is_selected(self, item_dict):
for related_url in self._get_related_urls(item_dict):
if related_url in self.path:
return True
# Resolve URL and check if it relates to a related views
if resolve(self.path).func in self._get_related_views(item_dict):
return True
return False

def _is_root(self, item_dict):
Expand Down
46 changes: 46 additions & 0 deletions menu_generator/tests/test_menu.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from django.http import HttpRequest
from django.test import TestCase

from .urls import testview
from .utils import TestUser, is_main_site, is_paid_user
from ..menu import MenuBase
from ..templatetags.menu_generator import get_menu
Expand Down Expand Up @@ -306,3 +307,48 @@ def test_generate_menu_selected_related_urls_submenu(self):
self.assertEqual(nav[0]["selected"], True)
self.assertEqual(nav[0]["submenu"][0]["selected"], True)
self.assertEqual(nav[0]["submenu"][1]["selected"], False)

def test_generate_menu_selected_related_views_simple(self):
self.request.user = TestUser(authenticated=True)
self.request.path = "/known-view/"
self.menu.save_user_state(self.request)
list_dict = [
{
"name": "parent1",
"url": "/user/account/",
"related_views": [testview],
}
]
nav = self.menu.generate_menu(list_dict)

self.assertEqual(len(nav), 1)
self.assertEqual(nav[0]["selected"], True)

def test_generate_menu_selected_related_views_submenu(self):
self.request.user = TestUser(authenticated=True)
self.request.path = "/known-view/"
self.menu.save_user_state(self.request)
list_dict = [
{
"name": "parent1",
"url": "/user/account/",
"submenu": [
{
"name": "child1",
"url": '/user/account/profile/',
"related_views": [testview]
},
{
"name": "child2",
"url": 'named_url',
"related_views": []
},
],
}
]
nav = self.menu.generate_menu(list_dict)

self.assertEqual(len(nav), 1)
self.assertEqual(nav[0]["selected"], True)
self.assertEqual(nav[0]["submenu"][0]["selected"], True)
self.assertEqual(nav[0]["submenu"][1]["selected"], False)
10 changes: 7 additions & 3 deletions menu_generator/tests/urls.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
from django.conf.urls import url

def testview(request):
return 'foo'

urlpatterns = [
url('', lambda: 'foo'),
url('named-url', lambda: 'foo', name='named_url'),
url('named-with-params/(?P<pk>\d+)/', lambda: 'foo', name='named_with_params')
url(r'named-url', lambda: 'foo', name='named_url'),
url(r'named-with-params/(?P<pk>\d+)/', lambda: 'foo', name='named_with_params'),
url(r'known-view', testview, name='known_view'),
url(r'', lambda: 'foo'),
]