g:序列化页面模型

Ric*_*ard 5 python django serialization json wagtail

我正在使用wagtail作为网站的REST后端。该网站是使用React构建的,并通过Wagtails API v2获取数据。

SPA网站必须能够显示w的页面预览。我的想法是serve_preview在页面模型上重写,然后简单地将新页面序列化为JSON并将其写入到可由前端访问的缓存中。但是我在将我的页面序列化为json时遇到麻烦。所有尝试都感觉很“骇人”

我已经尝试过使用序列化程序中内置的w的扩展名,但是没有成功:

豁免1:

   def serve_preview(self, request, mode_name):

        from wagtail.api.v2.endpoints import PagesAPIEndpoint

        endpoint = PagesAPIEndpoint()
        setattr(request, 'wagtailapi_router',
                WagtailAPIRouter('wagtailapi_v2'))
        endpoint.request = request
        endpoint.action = None
        endpoint.kwargs = {'slug': self.slug, 'pk': self.pk}
        endpoint.lookup_field = 'pk'

        serializer = endpoint.get_serializer(self)
Run Code Online (Sandbox Code Playgroud)

觉得在这里使用路由器并设置一堆attrs非常丑陋

尝试2:

 def serve_preview(self, request, mode_name):
    from wagtail.api.v2.endpoints import PagesAPIEndpoint

    fields = PagesAPIEndpoint.get_available_fields(self)
    if hasattr(self, 'api_fields'):
        fields.extend(self.api_fields)
    serializer_class = get_serializer_class(
        type(self), fields, meta_fields=[PagesAPIEndpoint.meta_fields], base=PageSerializer)
    serializer = serializer_class(self)
Run Code Online (Sandbox Code Playgroud)

更好,但我遇到了上下文问题:

Traceback (most recent call last):
...
File "/usr/local/lib/python3.5/site-packages/wagtail/api/v2/serializers.py", line 92, in to_representation    
self.context['view'].seen_types[name] = page.specific_class
    KeyError: 'view'
Run Code Online (Sandbox Code Playgroud)

有困难吗?

Ric*_*ard 3

通过深入研究源代码解决了这个问题。

首先定义一个空的虚拟视图:

class DummyView(GenericViewSet):

    def __init__(self, *args, **kwargs):
        super(DummyView, self).__init__(*args, **kwargs)

        # seen_types is a mapping of type name strings (format: "app_label.ModelName")
        # to model classes. When an object is serialised in the API, its model
        # is added to this mapping. This is used by the Admin API which appends a
        # summary of the used types to the response.
        self.seen_types = OrderedDict()
Run Code Online (Sandbox Code Playgroud)

然后使用此视图并手动设置序列化器的上下文。我也在我的上下文中使用与我的 api 相同的路由器。它具有由 PageSerializer 调用来解析某些字段的方法。有点奇怪,它与 wagtail api 如此紧密地耦合,但至少这是有效的:

def serve_preview(self, request, mode_name):

        import starrepublic.api as StarApi

        fields = StarApi.PagesAPIEndpoint.get_available_fields(self)
        if hasattr(self, 'api_fields'):
            fields.extend(self.api_fields)
        serializer_class = get_serializer_class(
            type(self), fields, meta_fields=[StarApi.PagesAPIEndpoint.meta_fields], base=PageSerializer)
        serializer = serializer_class(
            self, context={'request': request, 'view': DummyView(), 'router': StarApi.api_router})
Run Code Online (Sandbox Code Playgroud)

不要忘记导入:

from wagtail.api.v2.serializers import get_serializer_class
from rest_framework.viewsets import GenericViewSet
from rest_framework import status
from rest_framework.response import Response
from django.http import JsonResponse
from django.http import HttpResponse
Run Code Online (Sandbox Code Playgroud)