Allow subclasses of PagesAPIViewSet override default Page model

- Built on original PR  and feedback on that solution
- Add unit tests and documentation
- Fix typo in API documentation for `CustomPagesAPIViewSet`
- Ensure that pk is used (not id) while filtering to prevent assumption that id is pk
pull/10928/head
Neeraj P Yetheendran 2023-09-15 17:00:23 +05:30 zatwierdzone przez LB (Ben Johnston)
rodzic 6009903c55
commit cdd6f1800c
6 zmienionych plików z 45 dodań i 6 usunięć
docs
advanced_topics/api/v2
releases
wagtail/api/v2

Wyświetl plik

@ -29,6 +29,7 @@ Changelog
* Add support for `placement` in the `human_readable_date` tooltip template tag (Rohit Sharma)
* Add breadcrumbs to generic model views (Sage Abdullah)
* Support passing extra context variables via the `{% component %}` tag (Matt Westcott)
* Allow subclasses of `PagesAPIViewSet` override default Page model via the `model` attribute (Neeraj Yetheendran, Herbert Poul)
* Fix: Ensure that StreamField's `FieldBlock`s correctly set the `required` and `aria-describedby` attributes (Storm Heg)
* Fix: Avoid an error when the moderation panel (admin dashboard) contains both snippets and private pages (Matt Westcott)
* Fix: When deleting collections, ensure the collection name is correctly shown in the success message (LB (Ben) Johnston)

Wyświetl plik

@ -732,6 +732,7 @@
* Faishal Manzar
* Rohit Sharma
* Subhajit Ghosh
* Neeraj Yetheendran
## Translators

Wyświetl plik

@ -56,7 +56,21 @@ class CustomPagesAPIViewSet(PagesAPIViewSet):
renderer_classes = [JSONRenderer]
name = "pages"
api_router.register_endpoint("pages", ProdPagesAPIViewSet)
api_router.register_endpoint("pages", CustomPagesAPIViewSet)
```
Or changing the desired model to use for page results.
```python
from rest_framework.renderers import JSONRenderer
# ...
class PostPagesAPIViewSet(PagesAPIViewSet):
model = models.BlogPage
api_router.register_endpoint("posts", PostPagesAPIViewSet)
```
Additionally, there is a base endpoint class you can use for adding different

Wyświetl plik

@ -41,6 +41,7 @@ depth: 1
* Add support for `placement` in `human_readable_date` the tooltip template tag (Rohit Sharma)
* Add breadcrumbs to generic model views (Sage Abdullah)
* Support passing extra context variables via the `{% component %}` tag (Matt Westcott)
* Allow subclasses of `PagesAPIViewSet` override default Page model via the `model` attribute (Neeraj Yetheendran, Herbert Poul)
### Bug fixes

Wyświetl plik

@ -1105,6 +1105,14 @@ class TestPageListingSearch(WagtailTestUtils, TransactionTestCase):
self.assertEqual(set(page_id_list), {16, 18, 19})
def test_search_with_invalid_type(self):
# Check that a 400 error is returned when the type doesn't exist
response = self.get_response(type="demosite.InvalidPageType", search="blog")
content = json.loads(response.content.decode("UTF-8"))
self.assertEqual(response.status_code, 400)
self.assertEqual(content, {"message": "type doesn't exist"})
def test_search_with_filter(self):
response = self.get_response(
title="Another blog post", search="blog", order="title"
@ -1808,3 +1816,13 @@ class TestPageCacheInvalidation(TestCase):
Page.objects.get(id=2).specific.save_revision()
purge.assert_not_called()
class TestPageViewSetSubclassing(PagesAPIViewSet):
model = models.BlogEntryPage
def test_get_queryset(self):
self.assertEqual(
self.get_queryset().model,
models.BlogEntryPage,
)

Wyświetl plik

@ -555,20 +555,24 @@ class PagesAPIViewSet(BaseAPIViewSet):
# Allow pages to be filtered to a specific type
try:
models = page_models_from_string(
request.GET.get("type", "wagtailcore.Page")
)
models_type = request.GET.get("type", None)
models = models_type and page_models_from_string(models_type) or []
except (LookupError, ValueError):
raise BadRequestError("type doesn't exist")
if not models:
return self.get_base_queryset()
if self.model == Page:
return self.get_base_queryset()
else:
return self.model.objects.filter(
pk__in=self.get_base_queryset().values_list("pk", flat=True)
)
elif len(models) == 1:
# If a single page type has been specified, swap out the Page-based queryset for one based on
# the specific page model so that we can filter on any custom APIFields defined on that model
return models[0].objects.filter(
id__in=self.get_base_queryset().values_list("id", flat=True)
pk__in=self.get_base_queryset().values_list("pk", flat=True)
)
else: # len(models) > 1