8000 prefer titles matching request language · django-cms/django-cms@e074b3e · GitHub
[go: up one dir, main page]

Skip to content

Commit e074b3e

Browse files
committed
prefer titles matching request language
1 parent e56b0f8 commit e074b3e

File tree

3 files changed

+54
-10
lines changed

3 files changed

+54
-10
lines changed

cms/test_utils/testcases.py

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
from django.template.context import Context
1616
from django.test import testcases
1717
from django.test.client import RequestFactory
18+
from django.utils import translation
1819
from django.urls import reverse
1920
from django.utils.http import urlencode
2021
from django.utils.timezone import now
@@ -408,10 +409,7 @@ def get_request(self, path=None, language=None, post_data=None, enforce_csrf_che
408409
path = self.get_pages_root()
409410

410411
if not language:
411-
if settings.USE_I18N:
412-
language = settings.LANGUAGES[0][0]
413-
else:
414-
language = settings.LANGUAGE_CODE
412+
language = translation.get_language()
415413

416414
if post_data:
417415
request = factory.post(path, post_data)

cms/tests/test_page.py

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import datetime
22
import os.path
33
import functools
4-
from unittest import skipIf
4+
from unittest import mock, skipIf
55

66
from django.conf import settings
77
from django.contrib.auth import get_user_model
@@ -11,7 +11,7 @@
1111
from django.http import HttpResponse, HttpResponseNotFound
1212
from django.urls import reverse
1313
from django.utils.timezone import now as tz_now
14-
from django.utils.translation import override as force_language
14+
from django.utils.translation import activate, override as force_language
1515

1616
from cms import constants
1717
from cms.api import create_page, add_plugin, create_title, publish_page
@@ -682,6 +682,35 @@ def test_get_page_without_final_slash(self):
682682
self.assertIsNotNone(found_page)
683683
self.assertFalse(found_page.publisher_is_draft)
684684

685+
def test_language_homograph(self):
686+
# a page about boots you can wear
687+
wearable_boot = create_page("boot", "nav_playground.html", "en", slug="boot",
688+
published=True)
689+
create_title('de', 'stiefel', wearable_boot, slug='stiefel')
690+
wearable_boot.publish('de')
691+
# a page about boats that float on water
692+
floating_boat = create_page("boat", "nav_playground.html", "en", slug="boat",
693+
published=True)
694+
create_title('de', 'boot', floating_boat, slug='boot')
695+
floating_boat.publish('de')
696+
697+
activate('en')
698+
request = self.get_request('/en/boot/')
699+
page = get_page_from_request(request)
700+
self.assertEqual(page.pk, wearable_boot.publisher_public_id)
701+
702+
activate('de')
703+
request = self.get_request('/de/boot/', language='de')
704+
page = get_page_from_request(request)
705+
self.assertEqual(page.pk, floating_boat.publisher_public_id)
706+
707+
def test_no_request_language_code(self):
708+
request = self.get_request('/any-page/')
709+
del request.LANGUAGE_CODE
710+
with mock.patch('cms.utils.page.get_page_from_path') as mock_page_from_path:
711+
get_page_from_request(request)
712+
self.assertIsNone(mock_page_from_path.call_args.kwargs['language_code'])
713+
685714
def test_get_page_from_request_without_cache_when_has_use_path_argument(self):
686715
request = self.get_request('/test')
687716
request._current_page_cache = True

cms/utils/page.py

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import re
22

3-
from django.db.models import Q
3+
from django.db.models import ExpressionWrapper, Q
4+
from django.db.models.fields import BooleanField
45
from django.urls import reverse
56
from django.utils import timezone
67
from django.utils.encoding import force_str
@@ -76,7 +77,7 @@ def get_page_queryset(site, draft=True, published=False):
7677
return Page.objects.public().on_site(site)
7778

7879

79-
def get_page_from_path(site, path, preview=False, draft=False):
80+
def get_page_from_path(site, path, preview=False, draft=False, language_code=None):
8081
"""
8182
Resolves a url path to a single page object.
8283
Returns None if page does not exist
@@ -92,6 +93,17 @@ def get_page_from_path(site, path, preview=False, draft=False):
9293
titles = titles.filter(publisher_is_draft=False)
9394
else:
9495
titles = titles.filter(published=True, publisher_is_draft=False)
96+
if language_code is not None:
97+
sublanguage = language_code
98+
language = sublanguage.split("-", maxsplit=1)[0]
99+
titles = titles.annotate(
100+
matches_sublanguage=ExpressionWrapper(
101+
Q(language=sublanguage), output_field=BooleanField()
102+
),
103+
matches_language=ExpressionWrapper(
104+
Q(language=language), output_field=BooleanField()
105+
),
106+
).order_by("-matches_sublanguage", "-matches_language")
95107
titles = titles.filter(path=(path or ''))
96108

97109
for title in titles.iterator():
@@ -163,10 +175,15 @@ def get_page_from_request(request, use_path=None, clean_path=None):
163175
path = path[:-1]
164176

165177
site = get_current_site()
166-
page = get_page_from_path(site, path, preview, draft)
178+
request_language_code = getattr(request, "LANGUAGE_CODE", None)
179+
page = get_page_from_path(
180+
site, path, preview, draft, language_code=request_language_code
181+
)
167182

168183
if draft and page and not user_can_view_page_draft(request.user, page):
169-
page = get_page_from_path(site, path, preview, draft=False)
184+
page = get_page_from_path(
185+
site, path, preview, draft=False, language_code=request_language_code
186+
)
170187

171188
# For public pages, check if any parent is hidden due to published dates
172189
# In this case the selected page is not reachable

0 commit comments

Comments
 (0)
0