kopia lustrzana https://github.com/wagtail/wagtail
* Fix #7007: Add ancestor_of API filter * Alter descendant_of_with_type test to find at least one pagepull/7084/head
rodzic
dba3a438c0
commit
aafd32b66f
docs/advanced_topics/api/v2
wagtail/api/v2
|
@ -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
|
||||
------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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',
|
||||
|
|
Ładowanie…
Reference in New Issue