mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-03-16 22:10:28 +00:00
Add get_base_queryset method to PagesAPIEndpoint
This method provides a single place to define a base queryset to be used as a base for filtering but also in the descendant_of and child_of filters. This improves parity between the Admin API and public API as well.
This commit is contained in:
parent
05f2f14a3d
commit
a2b97737eb
3 changed files with 54 additions and 79 deletions
|
|
@ -3,10 +3,7 @@ from collections import OrderedDict
|
|||
from rest_framework.authentication import SessionAuthentication
|
||||
|
||||
from wagtail.api.v2.endpoints import PagesAPIViewSet
|
||||
from wagtail.api.v2.filters import (
|
||||
ChildOfFilter, DescendantOfFilter, FieldsFilter, OrderingFilter,
|
||||
SearchFilter)
|
||||
from wagtail.api.v2.utils import BadRequestError, filter_page_type, page_models_from_string
|
||||
from wagtail.api.v2.utils import filter_page_type
|
||||
from wagtail.core.models import Page
|
||||
|
||||
from .filters import ForExplorerFilter, HasChildrenFilter
|
||||
|
|
@ -17,16 +14,10 @@ class PagesAdminAPIViewSet(PagesAPIViewSet):
|
|||
base_serializer_class = AdminPageSerializer
|
||||
authentication_classes = [SessionAuthentication]
|
||||
|
||||
# Use unrestricted child_of/descendant_of filters
|
||||
# Add has_children filter
|
||||
filter_backends = [
|
||||
FieldsFilter,
|
||||
ChildOfFilter,
|
||||
DescendantOfFilter,
|
||||
ForExplorerFilter,
|
||||
# Add has_children and for_explorer filters
|
||||
filter_backends = PagesAPIViewSet.filter_backends + [
|
||||
HasChildrenFilter,
|
||||
OrderingFilter,
|
||||
SearchFilter,
|
||||
ForExplorerFilter,
|
||||
]
|
||||
|
||||
meta_fields = PagesAPIViewSet.meta_fields + [
|
||||
|
|
@ -57,16 +48,20 @@ class PagesAdminAPIViewSet(PagesAPIViewSet):
|
|||
'has_children'
|
||||
])
|
||||
|
||||
def get_queryset(self):
|
||||
request = self.request
|
||||
def get_root_page(self):
|
||||
"""
|
||||
Returns the page that is used when the `&child_of=root` filter is used.
|
||||
"""
|
||||
return Page.get_first_root_node()
|
||||
|
||||
# Allow pages to be filtered to a specific type
|
||||
try:
|
||||
models = page_models_from_string(request.GET.get('type', 'wagtailcore.Page'))
|
||||
except (LookupError, ValueError):
|
||||
raise BadRequestError("type doesn't exist")
|
||||
def get_base_queryset(self, models=None):
|
||||
"""
|
||||
Returns a queryset containing all pages that can be seen by this user.
|
||||
|
||||
if not models:
|
||||
This is used as the base for get_queryset and is also used to find the
|
||||
parent pages when using the child_of and descendant_of filters as well.
|
||||
"""
|
||||
if models is None:
|
||||
models = [Page]
|
||||
|
||||
if len(models) == 1:
|
||||
|
|
@ -77,6 +72,11 @@ class PagesAdminAPIViewSet(PagesAPIViewSet):
|
|||
# Filter pages by specified models
|
||||
queryset = filter_page_type(queryset, models)
|
||||
|
||||
return queryset
|
||||
|
||||
def get_queryset(self):
|
||||
queryset = super().get_queryset()
|
||||
|
||||
# Hide root page
|
||||
# TODO: Add "include_root" flag
|
||||
queryset = queryset.exclude(depth=1).specific()
|
||||
|
|
|
|||
|
|
@ -14,9 +14,7 @@ from rest_framework.viewsets import GenericViewSet
|
|||
from wagtail.api import APIField
|
||||
from wagtail.core.models import Page
|
||||
|
||||
from .filters import (
|
||||
FieldsFilter, OrderingFilter, RestrictedChildOfFilter, RestrictedDescendantOfFilter,
|
||||
SearchFilter)
|
||||
from .filters import ChildOfFilter, DescendantOfFilter, FieldsFilter, OrderingFilter, SearchFilter
|
||||
from .pagination import WagtailPagination
|
||||
from .serializers import BaseSerializer, PageSerializer, get_serializer_class
|
||||
from .utils import (
|
||||
|
|
@ -366,8 +364,8 @@ class PagesAPIViewSet(BaseAPIViewSet):
|
|||
base_serializer_class = PageSerializer
|
||||
filter_backends = [
|
||||
FieldsFilter,
|
||||
RestrictedChildOfFilter,
|
||||
RestrictedDescendantOfFilter,
|
||||
ChildOfFilter,
|
||||
DescendantOfFilter,
|
||||
OrderingFilter,
|
||||
SearchFilter
|
||||
]
|
||||
|
|
@ -401,16 +399,20 @@ class PagesAPIViewSet(BaseAPIViewSet):
|
|||
name = 'pages'
|
||||
model = Page
|
||||
|
||||
def get_queryset(self):
|
||||
request = self.request
|
||||
def get_root_page(self):
|
||||
"""
|
||||
Returns the page that is used when the `&child_of=root` filter is used.
|
||||
"""
|
||||
return self.request.site.root_page
|
||||
|
||||
# Allow pages to be filtered to a specific type
|
||||
try:
|
||||
models = page_models_from_string(request.GET.get('type', 'wagtailcore.Page'))
|
||||
except (LookupError, ValueError):
|
||||
raise BadRequestError("type doesn't exist")
|
||||
def get_base_queryset(self, models=None):
|
||||
"""
|
||||
Returns a queryset containing all pages that can be seen by this user.
|
||||
|
||||
if not models:
|
||||
This is used as the base for get_queryset and is also used to find the
|
||||
parent pages when using the child_of and descendant_of filters as well.
|
||||
"""
|
||||
if models is None:
|
||||
models = [Page]
|
||||
|
||||
if len(models) == 1:
|
||||
|
|
@ -425,14 +427,25 @@ class PagesAPIViewSet(BaseAPIViewSet):
|
|||
queryset = queryset.public().live()
|
||||
|
||||
# Filter by site
|
||||
if request.site:
|
||||
queryset = queryset.descendant_of(request.site.root_page, inclusive=True)
|
||||
if self.request.site:
|
||||
queryset = queryset.descendant_of(self.request.site.root_page, inclusive=True)
|
||||
else:
|
||||
# No sites configured
|
||||
queryset = queryset.none()
|
||||
|
||||
return queryset
|
||||
|
||||
def get_queryset(self):
|
||||
request = self.request
|
||||
|
||||
# Allow pages to be filtered to a specific type
|
||||
try:
|
||||
models = page_models_from_string(request.GET.get('type', 'wagtailcore.Page'))
|
||||
except (LookupError, ValueError):
|
||||
raise BadRequestError("type doesn't exist")
|
||||
|
||||
return self.get_base_queryset(models)
|
||||
|
||||
def get_object(self):
|
||||
base = super().get_object()
|
||||
return base.specific
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from wagtail.core.models import Page
|
|||
from wagtail.search.backends import get_search_backend
|
||||
from wagtail.search.backends.base import FilterFieldError, OrderByFieldError
|
||||
|
||||
from .utils import BadRequestError, pages_for_site, parse_boolean
|
||||
from .utils import BadRequestError, parse_boolean
|
||||
|
||||
|
||||
class FieldsFilter(BaseFilterBackend):
|
||||
|
|
@ -132,12 +132,6 @@ class ChildOfFilter(BaseFilterBackend):
|
|||
Implements the ?child_of filter used to filter the results to only contain
|
||||
pages that are direct children of the specified page.
|
||||
"""
|
||||
def get_root_page(self, request):
|
||||
return Page.get_first_root_node()
|
||||
|
||||
def get_page_by_id(self, request, page_id):
|
||||
return Page.objects.get(id=page_id)
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
if 'child_of' in request.GET:
|
||||
try:
|
||||
|
|
@ -145,10 +139,10 @@ class ChildOfFilter(BaseFilterBackend):
|
|||
if parent_page_id < 0:
|
||||
raise ValueError()
|
||||
|
||||
parent_page = self.get_page_by_id(request, parent_page_id)
|
||||
parent_page = view.get_base_queryset().get(id=parent_page_id)
|
||||
except ValueError:
|
||||
if request.GET['child_of'] == 'root':
|
||||
parent_page = self.get_root_page(request)
|
||||
parent_page = view.get_root_page()
|
||||
else:
|
||||
raise BadRequestError("child_of must be a positive integer")
|
||||
except Page.DoesNotExist:
|
||||
|
|
@ -160,30 +154,11 @@ class ChildOfFilter(BaseFilterBackend):
|
|||
return queryset
|
||||
|
||||
|
||||
class RestrictedChildOfFilter(ChildOfFilter):
|
||||
"""
|
||||
A restricted version of ChildOfFilter that only allows pages in the current
|
||||
site to be specified.
|
||||
"""
|
||||
def get_root_page(self, request):
|
||||
return request.site.root_page
|
||||
|
||||
def get_page_by_id(self, request, page_id):
|
||||
site_pages = pages_for_site(request.site)
|
||||
return site_pages.get(id=page_id)
|
||||
|
||||
|
||||
class DescendantOfFilter(BaseFilterBackend):
|
||||
"""
|
||||
Implements the ?decendant_of filter which limits the set of pages to a
|
||||
particular branch of the page tree.
|
||||
"""
|
||||
def get_root_page(self, request):
|
||||
return Page.get_first_root_node()
|
||||
|
||||
def get_page_by_id(self, request, page_id):
|
||||
return Page.objects.get(id=page_id)
|
||||
|
||||
def filter_queryset(self, request, queryset, view):
|
||||
if 'descendant_of' in request.GET:
|
||||
if hasattr(queryset, '_filtered_by_child_of'):
|
||||
|
|
@ -193,10 +168,10 @@ class DescendantOfFilter(BaseFilterBackend):
|
|||
if parent_page_id < 0:
|
||||
raise ValueError()
|
||||
|
||||
parent_page = self.get_page_by_id(request, parent_page_id)
|
||||
parent_page = view.get_base_queryset().get(id=parent_page_id)
|
||||
except ValueError:
|
||||
if request.GET['descendant_of'] == 'root':
|
||||
parent_page = self.get_root_page(request)
|
||||
parent_page = view.get_root_page()
|
||||
else:
|
||||
raise BadRequestError("descendant_of must be a positive integer")
|
||||
except Page.DoesNotExist:
|
||||
|
|
@ -205,16 +180,3 @@ class DescendantOfFilter(BaseFilterBackend):
|
|||
queryset = queryset.descendant_of(parent_page)
|
||||
|
||||
return queryset
|
||||
|
||||
|
||||
class RestrictedDescendantOfFilter(DescendantOfFilter):
|
||||
"""
|
||||
A restricted version of DecendantOfFilter that only allows pages in the current
|
||||
site to be specified.
|
||||
"""
|
||||
def get_root_page(self, request):
|
||||
return request.site.root_page
|
||||
|
||||
def get_page_by_id(self, request, page_id):
|
||||
site_pages = pages_for_site(request.site)
|
||||
return site_pages.get(id=page_id)
|
||||
|
|
|
|||
Loading…
Reference in a new issue