Repository: digitalfabrik/integreat-cms

Issue:
API: all pages endpoint per language
Endpoint for all pages of one language. This must be Integreat API v3 compatible.

Pages whose parent page is not public should not be delivered either.

https://github.com/Integreat/cms/wiki/REST-APIv3-Documentation#pageseventslocationsdisclaimer


Discussion:

Resolving patch:
diff --git a/backend/api/urls.py b/backend/api/urls.py
--- a/backend/api/urls.py
+++ b/backend/api/urls.py
@@ -7,6 +7,7 @@
 from .v3.feedback import feedback
 from .v3.languages import languages
 from .v3.regions import regions, liveregions, hiddenregions, pushnew
+from .v3.pages import pages
 from .v3.push_notifications import sent_push_notifications
 
 
@@ -37,5 +38,6 @@
         url(r'languages$', languages),
         url(r'(?P<lan_code>[-\w]+)/sent_push_notifications/$', sent_push_notifications),
         url(r'(?P<languages>[-\w]+)/feedback/$', feedback),
+        url(r'(?P<language_code>[-\w]+)/pages/$', pages),
     ])),
 ]
diff --git a/backend/api/v3/pages.py b/backend/api/v3/pages.py
new file mode 100644
--- /dev/null
+++ b/backend/api/v3/pages.py
@@ -0,0 +1,41 @@
+from django.http import JsonResponse
+
+from cms.models import Region
+
+
+def transform_page(page_translation):
+    if page_translation.page.parent:
+        parent = {
+            'id': page_translation.page.parent.id,
+            'url': page_translation.page.parent.get_translation(
+                page_translation.language.code
+            ).permalink,
+            'path': page_translation.page.parent.get_translation(
+                page_translation.language.code
+            ).slug,
+        }
+    else:
+        parent = None
+    return {
+        'id': page_translation.id,
+        'url': page_translation.permalink,
+        'path': page_translation.slug,
+        'title': page_translation.title,
+        'modified_gmt': page_translation.last_updated,
+        'excerpt': page_translation.text,
+        'content': page_translation.text,
+        'parent': parent,
+        'order': page_translation.page.lft, # use left edge indicator of mptt model for order
+        'available_languages': page_translation.available_languages,
+        'thumbnail': None,
+        'hash': None
+    }
+
+def pages(request, region_slug, language_code):
+    region = Region.objects.get(slug=region_slug)
+    result = []
+    for page in region.pages.all():
+        page_translation = page.get_public_translation(language_code)
+        if page_translation:
+            result.append(transform_page(page_translation))
+    return JsonResponse(result, safe=False)  # Turn off Safe-Mode to allow serializing arrays
diff --git a/backend/cms/models/page.py b/backend/cms/models/page.py
--- a/backend/cms/models/page.py
+++ b/backend/cms/models/page.py
@@ -5,7 +5,6 @@
 
 from django.db import models
 from django.conf import settings
-from django.core.exceptions import ObjectDoesNotExist
 from django.urls import reverse
 from django.utils import timezone
 from django.utils.translation import ugettext_lazy as _
@@ -61,16 +60,21 @@ def languages(self):
         page_translations = self.page_translations.prefetch_related('language').all()
         languages = []
         for page_translation in page_translations:
-            languages.append(page_translation.language)
+            if page_translation.language not in languages:
+                languages.append(page_translation.language)
         return languages
 
     def get_translation(self, language_code):
-        try:
-            page_translation = self.page_translations.filter(
-                language__code=language_code).order_by('-version').first()
-        except ObjectDoesNotExist:
-            page_translation = None
-        return page_translation
+        return self.page_translations.filter(
+            language__code=language_code
+        ).order_by('-version').first()
+
+    def get_public_translation(self, language_code):
+        return self.page_translations.filter(
+            language__code=language_code,
+            public=True,
+            status='reviewed',
+        ).order_by('-version').first()
 
     def get_absolute_url(self):
         return reverse('edit_page', kwargs={
@@ -182,6 +186,20 @@ def permalink(self):
             self.page.region.slug, self.language.code, self.ancestor_path, self.slug
         )
 
+    @property
+    def available_languages(self):
+        languages = self.page.languages
+        languages.remove(self.language)
+        available_languages = {}
+        for language in languages:
+            other_translation = self.page.get_public_translation(language.code)
+            if other_translation:
+                available_languages[language.code] = {
+                    'id': other_translation.id,
+                    'url': other_translation.permalink
+                }
+        return available_languages
+
     def __str__(self):
         return '(id: {}, slug: {})'.format(self.id, self.slug)
 


Test patch: