Repository: digitalfabrik/integreat-cms

Issue:
`MultipleObjectsReturned` in page children API endpoint
### Describe the Bug
<!-- A clear and concise description of what the bug is. -->
When the children of a page with more than one version with the same slug are requested via the `url` parameter, the error `MultipleObjectsReturned` gets thrown.

### Steps to Reproduce

1. Go to the region Augsbug
2. Create at least one additional version of the Willkommen page with the same slug
3. Open http://localhost:8000/api/augsburg/de/children?url=willkommen
4. See error

### Expected Behavior
<!-- A clear and concise description of what you expected to happen. -->
The children of the page should be returned

### Actual Behavior
<!-- A clear and concise description of what actually happened. -->
The following error appears:
```
Traceback (most recent call last):
  File "/opt/integreat-cms/.venv/lib/python3.8/site-packages/django/core/handlers/exception.py", line 47, in inner
    response = get_response(request)
  File "/opt/integreat-cms/.venv/lib/python3.8/site-packages/django/core/handlers/base.py", line 181, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/opt/integreat-cms/.venv/lib/python3.8/site-packages/integreat_cms/api/decorators.py", line 112, in wrap
    return function(request, *args, **kwargs)
  File "/opt/integreat-cms/.venv/lib/python3.8/site-packages/integreat_cms/api/v3/pages.py", line 184, in children
    root_pages = [get_single_page(request, language_slug)]
  File "/opt/integreat-cms/.venv/lib/python3.8/site-packages/integreat_cms/api/v3/pages.py", line 116, in get_single_page
    page = get_object_or_404(
  File "/opt/integreat-cms/.venv/lib/python3.8/site-packages/django/shortcuts.py", line 76, in get_object_or_404
    return queryset.get(*args, **kwargs)
  File "/opt/integreat-cms/.venv/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/opt/integreat-cms/.venv/lib/python3.8/site-packages/cacheops/query.py", line 351, in get
    return qs._no_monkey.get(qs, *args, **kwargs)
  File "/opt/integreat-cms/.venv/lib/python3.8/site-packages/django/db/models/query.py", line 439, in get
    raise self.model.MultipleObjectsReturned(
integreat_cms.cms.models.pages.page.Page.MultipleObjectsReturned: get() returned more than one Page -- it returned more than 20!
```

### Additional Information
<!-- Add any other context (e.g. logs, screenshots, etc.) about the problem here. -->

The problem is that the `get_object_or_404()` doesn't work with reverse foreign keys, because the same element might be in the queryset multiple times, so this is the culprit:
https://github.com/digitalfabrik/integreat-cms/blob/810bd2f3be861db0148a5e0410b5878ee59bfa17/integreat_cms/api/v3/pages.py#L116-L120
We probably need to add a `distinct()` here and throw an `Http404` manually without the shortcut method.


Discussion:

Resolving patch:
diff --git a/integreat_cms/api/v3/pages.py b/integreat_cms/api/v3/pages.py
--- a/integreat_cms/api/v3/pages.py
+++ b/integreat_cms/api/v3/pages.py
@@ -113,11 +113,14 @@ def get_single_page(request, language_slug):
         # The last path component of the url is the page translation slug
         page_translation_slug = url.split("/")[-1]
         # Get page by filtering for translation slug and translation language slug
-        page = get_object_or_404(
-            region.pages,
+        filtered_pages = region.pages.filter(
             translations__slug=page_translation_slug,
             translations__language__slug=language_slug,
-        )
+        ).distinct()
+
+        if len(filtered_pages) != 1:
+            raise Http404("No matching page translation found for url.")
+        page = filtered_pages[0]
 
     else:
         raise RuntimeError("Either the id or the url parameter is required.")


Test patch: