feat(api/2): Allow multiple page types to be specified in type filter

pull/1974/head
Karl Hobley 2015-10-12 13:26:53 +01:00
rodzic 30ec65fc13
commit 40de7d9090
3 zmienionych plików z 64 dodań i 12 usunięć

Wyświetl plik

@ -15,7 +15,6 @@ from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer
from wagtail.wagtailcore.models import Page
from wagtail.wagtailimages.models import get_image_model
from wagtail.wagtaildocs.models import Document
from wagtail.wagtailcore.utils import resolve_model_string
from .filters import (
FieldsFilter, OrderingFilter, SearchFilter,
@ -23,7 +22,7 @@ from .filters import (
)
from .pagination import WagtailPagination
from .serializers import BaseSerializer, PageSerializer, DocumentSerializer, ImageSerializer, get_serializer_class
from .utils import BadRequestError
from .utils import BadRequestError, page_models_from_string, filter_page_type
class BaseAPIEndpoint(GenericViewSet):
@ -204,19 +203,24 @@ class PagesAPIEndpoint(BaseAPIEndpoint):
request = self.request
# Allow pages to be filtered to a specific type
if 'type' not in request.GET:
model = Page
try:
models = page_models_from_string(request.GET.get('type', 'wagtailcore.Page'))
except (LookupError, ValueError):
raise BadRequestError("type doesn't exist")
if not models:
models = [Page]
if len(models) == 1:
queryset = models[0].objects.all()
else:
model_name = request.GET['type']
try:
model = resolve_model_string(model_name)
except LookupError:
raise BadRequestError("type doesn't exist")
if not issubclass(model, Page):
raise BadRequestError("type doesn't exist")
queryset = Page.objects.all()
# Filter pages by specified models
queryset = filter_page_type(queryset, models)
# Get live pages that are not in a private section
queryset = model.objects.public().live()
queryset = queryset.public().live()
# Filter by site
queryset = queryset.descendant_of(request.site.root_page, inclusive=True)

Wyświetl plik

@ -88,6 +88,9 @@ class TestPageListing(TestCase):
for page in content['results']:
self.assertEqual(page['meta']['type'], 'demosite.BlogEntryPage')
# All fields in specific type available
self.assertEqual(set(page.keys()), {'id', 'meta', 'title', 'related_links', 'date', 'body', 'tags', 'feed_image', 'carousel_items'})
def test_type_filter_total_count(self):
response = self.get_response(type='demosite.BlogEntryPage')
content = json.loads(response.content.decode('UTF-8'))
@ -95,6 +98,27 @@ class TestPageListing(TestCase):
# Total count must be reduced as this filters the results
self.assertEqual(content['total_count'], 3)
def test_type_filter_multiple(self):
response = self.get_response(type='demosite.BlogEntryPage,demosite.EventPage')
content = json.loads(response.content.decode('UTF-8'))
blog_page_seen = False
event_page_seen = False
for page in content['results']:
self.assertIn(page['meta']['type'], ['demosite.BlogEntryPage', 'demosite.EventPage'])
if page['meta']['type'] == 'demosite.BlogEntryPage':
blog_page_seen = True
elif page['meta']['type'] == 'demosite.EventPage':
event_page_seen = True
# Only generic fields available
self.assertEqual(set(page.keys()), {'id', 'meta', 'title'})
self.assertTrue(blog_page_seen, "No blog pages were found in the results")
self.assertTrue(event_page_seen, "No event pages were found in the results")
def test_non_existant_type_gives_error(self):
response = self.get_response(type='demosite.IDontExist')
content = json.loads(response.content.decode('UTF-8'))

Wyświetl plik

@ -2,6 +2,7 @@ from django.conf import settings
from django.utils.six.moves.urllib.parse import urlparse
from wagtail.wagtailcore.models import Page
from wagtail.wagtailcore.utils import resolve_model_string
class BadRequestError(Exception):
@ -27,3 +28,26 @@ def pages_for_site(site):
pages = Page.objects.public().live()
pages = pages.descendant_of(site.root_page, inclusive=True)
return pages
def page_models_from_string(string):
page_models = []
for sub_string in string.split(','):
page_model = resolve_model_string(sub_string)
if not issubclass(page_model, Page):
raise ValueError("Model is not a page")
page_models.append(page_model)
return tuple(page_models)
def filter_page_type(queryset, page_models):
qs = queryset.none()
for model in page_models:
qs |= queryset.type(model)
return qs