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

feat: Add API endpoint for page aliases with tests and docs #14

Open
wants to merge 1 commit into
base: main
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
17 changes: 17 additions & 0 deletions djangocms_rest/serializers/aliasserializer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from rest_framework import serializers
from cms.models import PageUrl


class AliasSerializer(serializers.Serializer):
url = serializers.CharField()
redirect_to = serializers.CharField()
language = serializers.CharField()
is_active = serializers.BooleanField()

def to_representation(self, instance):
return {
'url': instance.path,
'redirect_to': instance.page.get_absolute_url(instance.language),
'language': instance.language,
'is_active': instance.page.is_published(instance.language)
}
1 change: 1 addition & 0 deletions djangocms_rest/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from . import views

urlpatterns = [
path("<slug:language>/aliases/", views.AliasList.as_view(), name="cms-alias-list"),
path("", views.LanguageList.as_view(), name="cms-language-list"),
path("<slug:language>/pages", views.PageList.as_view(), name="cms-page-list"),
path("<slug:language>/pages/", views.PageDetail.as_view(), name="cms-page-root"),
Expand Down
29 changes: 29 additions & 0 deletions djangocms_rest/views.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from cms.models import Page, PageUrl, Placeholder, PageContent
from djangocms_rest.serializers.aliasserializer import AliasSerializer
from cms.utils.conf import get_languages
from cms.utils.i18n import get_language_tuple
from cms.utils.page_permissions import user_can_view_page
Expand Down Expand Up @@ -92,6 +93,34 @@ def get(self, request, language, path="", format=None):
return Response(serializer.data)


class AliasList(APIView):
"""
List of all page aliases for a given language.
Returns URL aliases and their redirect targets.
"""

def get(self, request, language, format=None):
site = get_current_site(request)
allowed_languages = [lang[0] for lang in get_language_tuple(site.pk)]
if language not in allowed_languages:
raise Http404

aliases = PageUrl.objects.get_for_site(site).filter(language=language)

# Filter out non-viewable pages for anonymous users
if request.user.is_anonymous:
aliases = aliases.filter(page__login_required=False)

# Filter based on page permissions
aliases = [
alias for alias in aliases
if user_can_view_page(request.user, alias.page)
]

serializer = AliasSerializer(aliases, many=True)
return Response(serializer.data)


class PlaceholderDetail(APIView):
"""Placeholder contain the dynamic content. This view retrieves the content as a
structured nested object.
Expand Down
1 change: 1 addition & 0 deletions tests/requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pytest
# requirements from setup.py
djangocms-picture>=2.1.0
djangocms-link>=2.2.1
Expand Down
51 changes: 51 additions & 0 deletions tests/test_rendering.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,57 @@ class RESTTestCase(CMSTestCase):
prefix = "http://testserver"


class AliasAPITestCase(RESTTestCase):
def setUp(self):
super().setUp()
# Create a test page with multiple language versions
self.page = create_page(
"test page",
template="INHERIT",
language="en",
published=True
)
# Create language versions
self.page.create_translation('de', title='Testseite')
self.page.create_translation('fr', title='page de test')

def test_alias_list(self):
"""Test that the alias list endpoint returns correct data"""
url = reverse("cms-alias-list", kwargs={"language": "en"})
response = self.client.get(url)

self.assertEqual(response.status_code, 200)
data = response.json()

# Verify structure of returned data
self.assertTrue(isinstance(data, list))
if len(data) > 0:
alias = data[0]
self.assertIn('url', alias)
self.assertIn('redirect_to', alias)
self.assertIn('language', alias)
self.assertIn('is_active', alias)

def test_alias_language_filter(self):
"""Test that aliases are correctly filtered by language"""
url = reverse("cms-alias-list", kwargs={"language": "de"})
response = self.client.get(url)

self.assertEqual(response.status_code, 200)
data = response.json()

# Verify all returned aliases are for German language
for alias in data:
self.assertEqual(alias['language'], 'de')

def test_invalid_language(self):
"""Test that invalid language code returns 404"""
url = reverse("cms-alias-list", kwargs={"language": "invalid"})
response = self.client.get(url)

self.assertEqual(response.status_code, 404)


class RenderingTestCase(RESTTestCase):
def _create_pages(self, page_list, parent=None):
new_pages = [create_page(
Expand Down
Loading