8000 Fixed #6158 -- Don't show unpublished pages in the menu. · django-cms/django-cms@36991b7 · GitHub
[go: up one dir, main page]

Skip to content

Commit 36991b7

Browse files
committed
Fixed #6158 -- Don't show unpublished pages in the menu.
1 parent c9661ea commit 36991b7

File tree

2 files changed

+101
-16
lines changed

2 files changed

+101
-16
lines changed

cms/cms_menus.py

Lines changed: 25 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from cms import constants
77
from cms.apphook_pool import apphook_pool
88
from cms.models import EmptyTitle
9+
from cms.utils import i18n
910
from cms.utils.compat import DJANGO_1_9
1011
from cms.utils.conf import get_cms_setting
1112
from cms.utils.i18n import get_fallback_languages, hide_untranslated
@@ -117,7 +118,7 @@ def get_menu_node_for_page(renderer, page, language):
117118
# Only run this if we have a translation in the requested language for this
118119
# object. The title cache should have been prepopulated in CMSMenu.get_nodes
119120
# but otherwise, just request the title normally
120-
if language in page.title_cache and page.application_urls:
121+
if page.title_cache.get(language) and page.application_urls:
121122
# it means it is an apphook
122123
app = apphook_pool.get_apphook(page.application_urls)
123124

@@ -136,7 +137,7 @@ def get_menu_node_for_page(renderer, page, language):
136137
if exts:
137138
attr['navigation_extenders'] = exts
138139

139-
translation = page.get_title_obj(language)
140+
translation = page.get_title_obj(language, fallback=True)
140141

141142
# Do we have a redirectURL?
142143
attr['redirect_url'] = translation.redirect # save redirect URL if any
@@ -149,7 +150,8 @@ def get_menu_node_for_page(renderer, page, language):
149150
parent_id=parent_id,
150151
attr=attr,
151152
visible=page.in_navigation,
152-
path=translation.path or translation.slug
153+
path=translation.path or translation.slug,
154+
language=(translation.language if translation.language != language else None),
153155
)
154156
return ret_node
155157

@@ -158,6 +160,8 @@ class CMSNavigationNode(NavigationNode):
158160

159161
def __init__(self, *args, **kwargs):
160162
self.path = kwargs.pop('path')
163+
# language is only used when we're dealing with a fallback
164+
self.language = kwargs.pop('language', None)
161165
super(CMSNavigationNode, self).__init__(*args, **kwargs)
162166

163167
def is_selected(self, request):
@@ -167,11 +171,17 @@ def is_selected(self, request):
167171
return False
168172
return page_id == self.id
169173

170-
def get_absolute_url(self):
174+
def _get_absolute_url(self):
171175
if self.attr['is_home']:
172176
return reverse('pages-root')
173177
return reverse('pages-details-by-slug', kwargs={"slug": self.path})
174178

179+
def get_absolute_url(self):
180+
if self.language:
181+
with i18n.force_language(self.language):
182+
return self._get_absolute_url()
183+
return self._get_absolute_url()
184+
175185

176186
class CMSMenu(Menu):
177187

@@ -186,7 +196,10 @@ def get_nodes(self, request):
186196
)
187197

188198
if hide_untranslated(lang, site.pk):
189-
nodes = nodes.filter(page__title_set__language=lang)
199+
if self.renderer.draft_mode_active:
200+
nodes = nodes.filter(page__title_set__language=lang)
201+
else:
202+
nodes = nodes.filter(page__publisher_public__title_set__language=lang)
190203
languages = [lang]
191204
else:
192205
fallbacks = get_fallback_languages(lang, site_id=site.pk)
@@ -210,10 +223,15 @@ def get_nodes(self, request):
210223
if not pages:
211224
return []
212225

226+
titles = Title.objects.filter(
227+
language__in=languages,
228+
publisher_is_draft=bool(self.renderer.draft_mode_active),
229+
)
230+
213231
lookup = Prefetch(
214232
'title_set',
215233
to_attr='filtered_translations',
216-
queryset=Title.objects.filter(language__in=languages)
234+
queryset=titles,
217235
)
218236

219237
if DJANGO_1_9:
@@ -233,13 +251,7 @@ def _page_to_node(page):
233251
# EmptyTitle is used to prevent the cms from trying
234252
# to find a translation in the database
235253
page.title_cache.setdefault(language, blank_title_cache[language])
236-
237-
menu_node = get_menu_node_for_page(
238-
renderer=self.renderer,
239-
page=page,
240-
language=lang,
241-
)
242-
return menu_node
254+
return get_menu_node_for_page(self.renderer, page, language=lang)
243255
return [_page_to_node(page=page) for page in pages]
244256

245257

cms/tests/test_menu.py

Lines changed: 76 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
from menus.models import CacheKey
1414
from menus.utils import mark_descendants, find_selected, cut_levels
1515

16-
from cms.api import create_page
16+
from cms.api import create_page, create_title
1717
from cms.cms_menus import get_visible_nodes
18-
from cms.models import Page, ACCESS_PAGE_AND_DESCENDANTS
18+
from cms.models import Page, PageNode, ACCESS_PAGE_AND_DESCENDANTS
1919
from cms.models.permissionmodels import GlobalPagePermission, PagePermission
2020
from cms.test_utils.project.sampleapp.cms_menus import SampleAppMenu, StaticMenu, StaticMenu2
2121
from cms.test_utils.fixtures.menus import (MenusFixture, SubMenusFixture,
@@ -289,7 +289,80 @@ def test_basic_cms_menu(self):
289289
# test the cms menu class
290290
menu = renderer.get_menu('CMSMenu')
291291
nodes = menu.get_nodes(request)
292-
self.assertEqual(len(nodes), len(self.get_all_pages()))
292+
pages = self.get_all_pages().order_by('publisher_public__nodes__path')
293+
self.assertEqual(len(nodes), len(pages))
294+
self.assertSequenceEqual(
295+
[node.get_absolute_url() for node in nodes],
296+
[page.get_absolute_url() for page in pages],
297+
)
298+
299+
def test_cms_menu_public_with_multiple_languages(self):
300+
for node in PageNode.objects.all():
301+
create_title(
302+
language='de',
303+
title=node.page.get_title('en'),
304+
page=node.page,
305+
slug='{}-de'.format(node.page.get_slug('en'))
306+
)
307+
308+
pages = self.get_all_pages().order_by('publisher_public__nodes__path')
309+
310+
# Fallbacks on
311+
request = self.get_request(language='de')
312+
renderer = menu_pool.get_renderer(request)
313+
menu = renderer.get_menu('CMSMenu')
314+
nodes = menu.get_nodes(request)
315+
self.assertEqual(len(nodes), len(pages))
316+
317+
with force_language('de'):
318+
# Current language is "de" but urls should still point
319+
# to "en" because of fallbacks.
320+
self.assertSequenceEqual(
321+
[node.get_absolute_url() for node in nodes],
322+
[page.get_absolute_url('en', fallback=False) for page in pages],
323+
)
324+
325+
# Fallbacks off
326+
request = self.get_request(language='de')
327+
lang_settings = copy.deepcopy(get_cms_setting('LANGUAGES'))
328+
lang_settings[1][1]['hide_untranslated'] = True
329+
330+
with self.settings(CMS_LANGUAGES=lang_settings):
331+
renderer = menu_pool.get_renderer(request)
332+
menu = renderer.get_menu('CMSMenu')
333+
nodes = menu.get_nodes(request)
334+
self.assertEqual(len(nodes), 0)
335+
336+
for node in PageNode.objects.all():
337+
node.page.publish('de')
338+
339+
# Fallbacks on
340+
# This time however, the "de" translations are published.
341+
request = self.get_request(language='de')
342+
renderer = menu_pool.get_renderer(request)
343+
menu = renderer.get_menu('CMSMenu')
344+
nodes = menu.get_nodes(request)
345+
self.assertEqual(len(nodes), len(pages))
346+
347+
with force_language('de'):
348+
self.assertSequenceEqual(
349+
[node.get_absolute_url() for node in nodes],
350+
[page.get_absolute_url('de', fallback=False) for page in pages],
351+
)
352+
353+
# Fallbacks off
354+
request = self.get_request(language='de')
355+
356+
with self.settings(CMS_LANGUAGES=lang_settings):
357+
renderer = menu_pool.get_renderer(request)
358+
menu = renderer.get_menu('CMSMenu')
359+
nodes = menu.get_nodes(request)
360+
361+
with force_language('de'):
362+
self.assertSequenceEqual(
363+
[node.get_absolute_url() for node in nodes],
364+
[page.get_absolute_url('de', fallback=False) for page in pages],
365+
)
293366

294367
def test_show_menu(self):
295368
root = self.get_page(1)

0 commit comments

Comments
 (0)
0