Fix : Add ancestor_of API filter ()

* Fix : Add ancestor_of API filter

* Alter descendant_of_with_type test to find at least one page
pull/7084/head
Jaap Roes 2021-04-22 18:23:26 +02:00 zatwierdzone przez GitHub
rodzic dba3a438c0
commit aafd32b66f
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
4 zmienionych plików z 79 dodań i 8 usunięć
docs/advanced_topics/api/v2

Wyświetl plik

@ -274,8 +274,7 @@ For example, to find a page with the slug "about":
Filtering by tree position (pages only)
---------------------------------------
Pages can additionally be filtered by their position of the tree. For this,
there are two parameters you can use: ``?child_of`` and ``?descendant_of``.
Pages can additionally be filtered by their relation to other pages in the tree.
The ``?child_of`` filter takes the id of a page and filters the list of results
to contain only direct children of that page.
@ -322,8 +321,17 @@ id of the homepage to the filter:
]
}
The ``?descendant_of`` filter also takes the id of a page but includes all
descendants (children of children) instead of just directly children.
The ``?ancestor_of`` filter takes the id of a page and filters the list
to only include ancestors of that page (parent, grandparent etc.) all the
way down to the site's root page.
For example, when combined with the ``type`` filter it can be used to
find the particular ``blog.BlogIndexPage`` a ``blog.BlogPage`` belongs
to. By itself, it can be used to to construct a breadcrumb trail from
the current page back to the site's root page.
The ``?descendant_of`` filter takes the id of a page and filter the list
to only include descendants of that page (children, grandchildren etc.).
Search
------

Wyświetl plik

@ -165,6 +165,29 @@ class ChildOfFilter(BaseFilterBackend):
return queryset
class AncestorOfFilter(BaseFilterBackend):
"""
Implements the ?ancestor filter which limits the set of pages to a
particular branch of the page tree.
"""
def filter_queryset(self, request, queryset, view):
if 'ancestor_of' in request.GET:
try:
descendant_page_id = int(request.GET['ancestor_of'])
if descendant_page_id < 0:
raise ValueError()
descendant_page = view.get_base_queryset().get(id=descendant_page_id)
except ValueError:
raise BadRequestError("ancestor_of must be a positive integer")
except Page.DoesNotExist:
raise BadRequestError("descendant page doesn't exist")
queryset = queryset.ancestor_of(descendant_page)
return queryset
class DescendantOfFilter(BaseFilterBackend):
"""
Implements the ?decendant_of filter which limits the set of pages to a

Wyświetl plik

@ -563,6 +563,44 @@ class TestPageListing(TestCase):
self.assertEqual(response.status_code, 400)
self.assertEqual(content, {'message': "parent page doesn't exist"})
# ANCESTOR OF FILTER
def test_ancestor_of_filter(self):
response = self.get_response(ancestor_of=10)
content = response.json()
page_id_list = self.get_page_id_list(content)
self.assertEqual(page_id_list, [2, 6])
def test_ancestor_of_with_type(self):
response = self.get_response(type='demosite.eventindexpage', ancestor_of=8)
content = response.json()
page_id_list = self.get_page_id_list(content)
self.assertEqual(page_id_list, [4])
def test_ancestor_of_unknown_page_gives_error(self):
response = self.get_response(ancestor_of=1000)
content = response.json()
self.assertEqual(response.status_code, 400)
self.assertEqual(content, {'message': "descendant page doesn't exist"})
def test_ancestor_of_not_integer_gives_error(self):
response = self.get_response(ancestor_of='abc')
content = response.json()
self.assertEqual(response.status_code, 400)
self.assertEqual(content, {'message': "ancestor_of must be a positive integer"})
def test_ancestor_of_home_page_ignores_root(self):
# Root page is not in any site, so pretend it doesn't exist
response = self.get_response(ancestor_of=2)
content = response.json()
page_id_list = self.get_page_id_list(content)
self.assertEqual(page_id_list, [])
# DESCENDANT OF FILTER
def test_descendant_of_filter(self):
@ -582,11 +620,11 @@ class TestPageListing(TestCase):
self.assertEqual(page_id_list, [4, 8, 9, 5, 16, 18, 19, 6, 10, 15, 17, 21, 22, 23, 20, 13, 14, 12])
def test_descendant_of_with_type(self):
response = self.get_response(type='tests.EventPage', descendant_of=6)
response = self.get_response(type='demosite.eventindexpage', descendant_of=2)
content = json.loads(response.content.decode('UTF-8'))
page_id_list = self.get_page_id_list(content)
self.assertEqual(page_id_list, [])
self.assertEqual(page_id_list, [4])
def test_descendant_of_unknown_page_gives_error(self):
response = self.get_response(descendant_of=1000)

Wyświetl plik

@ -15,8 +15,8 @@ from wagtail.api import APIField
from wagtail.core.models import Page, Site
from .filters import (
ChildOfFilter, DescendantOfFilter, FieldsFilter, LocaleFilter, OrderingFilter, SearchFilter,
TranslationOfFilter)
AncestorOfFilter, ChildOfFilter, DescendantOfFilter, FieldsFilter, LocaleFilter, OrderingFilter,
SearchFilter, TranslationOfFilter)
from .pagination import WagtailPagination
from .serializers import BaseSerializer, PageSerializer, get_serializer_class
from .utils import (
@ -366,6 +366,7 @@ class PagesAPIViewSet(BaseAPIViewSet):
filter_backends = [
FieldsFilter,
ChildOfFilter,
AncestorOfFilter,
DescendantOfFilter,
OrderingFilter,
TranslationOfFilter,
@ -375,6 +376,7 @@ class PagesAPIViewSet(BaseAPIViewSet):
known_query_parameters = BaseAPIViewSet.known_query_parameters.union([
'type',
'child_of',
'ancestor_of',
'descendant_of',
'translation_of',
'locale',