Wagtail:序列化页面模型
Wagtail: Serializing page model
我正在使用 wagtail 作为网站的 REST 后端。该网站是使用 react 构建的,并通过 wagtails API v2.
获取数据
SPA 网站需要能够在 wagtail 中显示页面预览。我的想法是覆盖页面模型上的 serve_preview
并简单地将新页面序列化为 JSON 并将其写入我的前端可以访问的缓存。但是我无法将我的页面序列化为 json。所有的尝试都感觉非常"hackish"
我已经多次尝试使用序列化程序中内置的 wagtails 扩展但没有成功:
尝试 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)
这里用router,设置一堆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)
更好,但我遇到了上下文问题:
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'
有什么困难吗?
可能是一个没有答案的答案,但我在 DRF、Wagtail 在 DRF 之上的分层以及需要缓存 json 结果方面也遇到过挑战(DRF 没有内置缓存据我所知,这是一个额外的挑战)。在最近的一个项目中,我最终只是在视图中构建了一个字典列表,然后使用 HttpResponse()
将它们发回,完全绕过了 DRF 和 Wagtail API。代码最终变得简单、可读且易于缓存:
import json
from django.http import HttpResponse
from django.core.cache import cache
data = cache.get('mydata')
if not data:
datalist = []
for foo in bar:
somedata = {}
# Populate somedata, "serializing" fields manually...
datalist.append(somedata)
# Cache for a week.
data = datalist
cache.set('mydata', datalist, 60 * 60 * 24 * 7)
return HttpResponse(json.dumps(data), content_type='application/json')
不如使用预构建的 REST 框架优雅,但有时更简单的方法效率更高...
通过深入研究源代码解决了这个问题。
首先定义一个空的虚拟视图:
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()
然后使用此视图并手动设置序列化程序的上下文。在我的上下文中,我也使用与 api 中相同的路由器。它具有由 PageSerializer 调用的方法来解析某些字段。有点奇怪,它与鹡鸰的耦合如此紧密 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})
别忘了导入:
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
我正在使用 wagtail 作为网站的 REST 后端。该网站是使用 react 构建的,并通过 wagtails API v2.
获取数据SPA 网站需要能够在 wagtail 中显示页面预览。我的想法是覆盖页面模型上的 serve_preview
并简单地将新页面序列化为 JSON 并将其写入我的前端可以访问的缓存。但是我无法将我的页面序列化为 json。所有的尝试都感觉非常"hackish"
我已经多次尝试使用序列化程序中内置的 wagtails 扩展但没有成功:
尝试 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)
这里用router,设置一堆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)
更好,但我遇到了上下文问题:
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'
有什么困难吗?
可能是一个没有答案的答案,但我在 DRF、Wagtail 在 DRF 之上的分层以及需要缓存 json 结果方面也遇到过挑战(DRF 没有内置缓存据我所知,这是一个额外的挑战)。在最近的一个项目中,我最终只是在视图中构建了一个字典列表,然后使用 HttpResponse()
将它们发回,完全绕过了 DRF 和 Wagtail API。代码最终变得简单、可读且易于缓存:
import json
from django.http import HttpResponse
from django.core.cache import cache
data = cache.get('mydata')
if not data:
datalist = []
for foo in bar:
somedata = {}
# Populate somedata, "serializing" fields manually...
datalist.append(somedata)
# Cache for a week.
data = datalist
cache.set('mydata', datalist, 60 * 60 * 24 * 7)
return HttpResponse(json.dumps(data), content_type='application/json')
不如使用预构建的 REST 框架优雅,但有时更简单的方法效率更高...
通过深入研究源代码解决了这个问题。
首先定义一个空的虚拟视图:
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()
然后使用此视图并手动设置序列化程序的上下文。在我的上下文中,我也使用与 api 中相同的路由器。它具有由 PageSerializer 调用的方法来解析某些字段。有点奇怪,它与鹡鸰的耦合如此紧密 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})
别忘了导入:
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