wagtail API: my pages不出现在/ API /cms/pages/中



我已经将我的wagtail配置为使用api并在/api/cms/pages/endpoint上提供页面。我有9页创建和发布。但是我只有默认的欢迎wagtail页面和它的子页面在这个端点上:

{
"meta": {
"total_count": 3
},
"items": [
{
"id": 2,
"meta": {
"type": "wagtailcore.Page",
"detail_url": "http://localhost/api/cms/pages/2/",
"html_url": "http://localhost/",
"slug": "home",
"first_published_at": "2022-06-10T09:07:28.066461Z"
},
"title": "Welcome to your new Wagtail site!"
},
{
"id": 10,
"meta": {
"type": "blog.BlogPage",
"detail_url": "http://localhost/api/cms/pages/10/",
"html_url": "http://localhost/test-blog/",
"slug": "test-blog",
"first_published_at": "2022-06-10T09:06:33.879559Z"
},
"title": "test blog"
},
{
"id": 11,
"meta": {
"type": "blog.PostPage",
"detail_url": "http://localhost/api/cms/pages/11/",
"html_url": "http://localhost/test-post/",
"slug": "test-post",
"first_published_at": "2022-06-10T09:06:51.974754Z"
},
"title": "test post"
}
]
}

我已经创建了一些BlogPages和PostPages,但他们没有出现在那里。我如何配置我的django/wagtail文件,使它们出现?这里的文档:https://docs.wagtail.org/en/stable/advanced_topics/api/v2/usage.html不是很详细…

这是我的models.py:

import urllib.parse
from django.http.response import JsonResponse, HttpResponseRedirect
from django.conf import settings
from django.db import models
from django.utils.module_loading import import_string
from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator
from modelcluster.fields import ParentalKey
from modelcluster.tags import ClusterTaggableManager
from taggit.models import Tag as TaggitTag
from taggit.models import TaggedItemBase
from wagtail.admin.edit_handlers import (
FieldPanel,
FieldRowPanel,
InlinePanel,
MultiFieldPanel,
PageChooserPanel,
StreamFieldPanel,
)
from wagtail.core.models import Page
from wagtail.images.edit_handlers import ImageChooserPanel
from wagtail.snippets.edit_handlers import SnippetChooserPanel
from wagtail.snippets.models import register_snippet
from wagtail.core.fields import StreamField
from wagtail.contrib.routable_page.models import RoutablePageMixin, route
from wagtail.search import index
from wagtail_headless_preview.models import HeadlessPreviewMixin
from .blocks import BodyBlock
from wagtail.api import APIField 
from .fields import TagField, CategoryField, DateTimeField
from wagtail.images.api.fields import ImageRenditionField
from django.db import models
class BasePage(HeadlessPreviewMixin, Page):
serializer_class = None
class Meta:
abstract = True
def get_component_data(self):
if not self.serializer_class:
raise Exception(f'serializer_class is not set {self.__class__.__name__}')
serializer_class = import_string(self.serializer_class)
return {
'page_type': self.__class__.__name__,
'page_content': serializer_class(self).data
}
def categories_list(self, context):
categories = BlogCategory.objects.all()
blog_page = context['blog_page']
data = [{
'name': category.name,
'slug': category.slug,
'url': blog_page.url + blog_page.reverse_subpage(
"post_by_category",
args=(
category.slug,
)
)
} for category in categories]
return data
def tags_list(self, context):
tags = Tag.objects.all()
blog_page = context['blog_page']
data = [{
'name': tag.name,
'slug': tag.slug,
'url': blog_page.url + blog_page.reverse_subpage(
"post_by_tag",
args=(
tag.slug,
)
)
} for tag in tags]
return data
def get_context(self, request, *args, **kwargs):
context = super().get_context(request)
context['page_component'] = self.get_component_data()
if 'blog_page' not in context:
context['blog_page'] = BlogPage.objects.first()
context['page_component']['categories_list'] = self.categories_list(context)
context['page_component']['tags_list'] = self.tags_list(context)
return context
def serve(self, request, *args, **kwargs):
if request.content_type == 'application/json':
context = self.get_context(request, *args, **kwargs)
return JsonResponse(context['page_component'])
else:
full_path = request.get_full_path()
return HttpResponseRedirect(urllib.parse.urljoin(settings.REACT_APP_BASE, full_path))

class BlogPage(RoutablePageMixin, BasePage):
serializer_class = "blog.serializers.BlogPageSerializer"
description = models.CharField(max_length=255, blank=True,)
content_panels = Page.content_panels + [FieldPanel("description", classname="full")]
def get_context(self, request, *args, **kwargs):
context = super().get_context(request, *args, **kwargs)
# https://docs.djangoproject.com/en/3.2/topics/pagination/#using-paginator-in-a-view-function
per_page = 2
paginator = Paginator(self.posts, per_page)
page = self.page_num
try:
posts = paginator.page(page)
except PageNotAnInteger:
posts = paginator.page(1)
except EmptyPage:
posts = paginator.page(1)
context['page_component']['children_pages'] = [
post.get_component_data()
for post in posts
]
context['page_component']['paginator'] = {
'per_page': per_page,
'current_page': posts.number,
'num_pages': posts.paginator.num_pages,
}
context['page_component']['filter_meta'] = {                   # new
'filter_type': getattr(self, 'filter_type', None),
'filter_term': getattr(self, 'filter_term', None),
}
return context
def get_posts(self):
return PostPage.objects.descendant_of(self).live()
@route(r'^tag/(?P<tag>[-w]+)/(?:page-(?P<page_num>d+)/)?')
def post_by_tag(self, request, tag, page_num=1, *args, **kwargs):
self.page_num = int(page_num)
self.filter_type = 'tag'                                     # new
self.filter_term = tag
self.posts = self.get_posts().filter(tags__slug=tag)
return self.serve(request)
@route(r'^category/(?P<category>[-w]+)/(?:page-(?P<page_num>d+)/)?')
def post_by_category(self, request, category, page_num=1, *args, **kwargs):
self.page_num = int(page_num)
self.filter_type = 'category'                                # new
self.filter_term = category
self.posts = self.get_posts().filter(categories__blog_category__slug=category)
return self.serve(request)
@route(r'^(?:page-(?P<page_num>d+)/)?$')
def post_list(self, request, page_num=1, *args, **kwargs):
self.page_num = int(page_num)
self.posts = self.get_posts()
return self.serve(request)

class PostPage(BasePage):
serializer_class = "blog.serializers.PostPageSerializer"
header_image = models.ForeignKey(
"wagtailimages.Image",
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="+",
)
body = StreamField(BodyBlock(), blank=True)
tags = ClusterTaggableManager(through="blog.PostPageTag", blank=True)
content_panels = Page.content_panels + [
ImageChooserPanel("header_image"),
InlinePanel("categories", label="category"),
FieldPanel("tags"),
StreamFieldPanel("body"),
]
search_fields = Page.search_fields + [
index.SearchField('title'),
index.SearchField('body'),
]
api_fields = ( 
APIField(
"header_image_url",
serializer=ImageRenditionField("max-1000x800", source="header_image"), 
),
"body",
APIField("owner"),
APIField("api_categories", serializer=CategoryField(source="categories")),#check if categories retrieved
APIField("api_tags", serializer=TagField(source="tags")), 
#APIField("pub_date",serializer=DateTimeField(format="%d %B %Y", source="first_published_at")),
)
class PostPageBlogCategory(models.Model):
page = ParentalKey(
"blog.PostPage", on_delete=models.CASCADE, related_name="categories"
)
blog_category = models.ForeignKey(
"blog.BlogCategory", on_delete=models.CASCADE, related_name="post_pages"
)
panels = [
SnippetChooserPanel("blog_category"),
]
class Meta:
unique_together = ("page", "blog_category")

@register_snippet
class BlogCategory(models.Model):
name = models.CharField(max_length=255)
slug = models.SlugField(unique=True, max_length=80)
panels = [
FieldPanel("name"),
FieldPanel("slug"),
]
def __str__(self):
return self.name
class Meta:
verbose_name = "Category"
verbose_name_plural = "Categories"

class PostPageTag(TaggedItemBase):
content_object = ParentalKey("PostPage", related_name="post_tags")

@register_snippet
class Tag(TaggitTag):
class Meta:
proxy = True

这里是url。py:

from django.contrib import admin
from django.urls import path, include
from django.conf import settings
from wagtail.core import urls as wagtail_urls
from wagtail.admin import urls as wagtailadmin_urls
from wagtail.documents import urls as wagtaildocs_urls
from blog.api import api_router
from blog.api import blog_router
urlpatterns = [
path('admin/', admin.site.urls),
path('cms-admin/', include(wagtailadmin_urls)),
path('documents/', include(wagtaildocs_urls)),
path('api/blog/', include(blog_router.urls)),#/posts, categories and tags to get the api pages
path('api/cms/', api_router.urls),#/pages to get the api pages
path('', include('custom_comments.urls')),
# For anything not caught by a more specific rule above, hand over to
# Wagtail's serving mechanism
path('', include(wagtail_urls)),
]
if settings.DEBUG:
from django.conf.urls.static import static
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
这是我的api。py
from django.contrib.contenttypes.models import ContentType
from django.urls import path
from rest_framework import serializers
from wagtail.api.v2.router import WagtailAPIRouter
from wagtail.api.v2.views import BaseAPIViewSet, PagesAPIViewSet
from wagtail.documents.api.v2.views import DocumentsAPIViewSet
from wagtail.images.api.v2.views import ImagesAPIViewSet
from wagtail.core.models import Page
from blog.serializers import CategorySerializer, TagSerializer
from blog.models import BlogCategory, Tag
from wagtail_headless_preview.models import PagePreview
from blog.views import CategorySet, PostPageSet, TagSet
from rest_framework import routers
api_router = WagtailAPIRouter("wagtailapi")
api_router.register_endpoint('pages', PagesAPIViewSet)
api_router.register_endpoint("images", ImagesAPIViewSet)
api_router.register_endpoint("documents", DocumentsAPIViewSet)
blog_router = routers.DefaultRouter() 
blog_router.register(r"posts", PostPageSet) 
blog_router.register(r"categories", CategorySet) 
blog_router.register(r"tags", TagSet)
class PagePreviewAPIViewSet(PagesAPIViewSet):
known_query_parameters = PagesAPIViewSet.known_query_parameters.union(
["content_type", "token"]
)
def listing_view(self, request):
page = self.get_object()
return page.serve(request)
def detail_view(self, request, pk):
page = self.get_object()
return page.serve(request)
def get_object(self):
app_label, model = self.request.GET["content_type"].split(".")
content_type = ContentType.objects.get(app_label=app_label, model=model)
page_preview = PagePreview.objects.get(
content_type=content_type, token=self.request.GET["token"]
)
page = page_preview.as_page()
if not page.pk:
# fake primary key to stop API URL routing from complaining
page.pk = 0
return page

api_router.register_endpoint("page_preview", PagePreviewAPIViewSet)

class CategoryAPIViewSet(BaseAPIViewSet):
base_serializer_class = CategorySerializer
filter_backends = []
meta_fields = []
body_fields = ['id', 'slug', 'name']
listing_default_fields = ['id', 'slug', 'name']
nested_default_fields = []
name = 'category'
model = BlogCategory

api_router.register_endpoint("category", CategoryAPIViewSet)

class TagAPIViewSet(BaseAPIViewSet):
base_serializer_class = TagSerializer
filter_backends = []
meta_fields = []
body_fields = ['id', 'slug', 'name']
listing_default_fields = ['id', 'slug', 'name']
nested_default_fields = []
name = 'tag'
model = Tag

api_router.register_endpoint("tag", TagAPIViewSet)

我将这些页面创建为根页面,而不是已配置站点的子页面:cms菜单中显示错误消息:

There is no site set up for this location. Pages created here will not be accessible at any URL until a site is associated with this location. Configure a site now.

然而,我还没有发现如何将几个页面附加到一个网站,当页面被创建为wagtail的根。只能将一个页面附加到一个站点,然后只能检索其子页面

最新更新