mirror of
https://github.com/Hopiu/wagtail.git
synced 2026-05-15 02:33:13 +00:00
Merged BaseSerializer with WagtailSerializer
Previously, WagtailSerializer and it's subclasses were responsible for serializing objects and it delegated serializing the dynamic fields to automatically generated subclasses of BaseSerializer. Now, these have been merged and all serializers are generated automatically for a particular request. The responsibility of generating the serializers is now in the endpoint.
This commit is contained in:
parent
32d0170882
commit
b3ca0412f5
2 changed files with 45 additions and 44 deletions
|
|
@ -20,14 +20,14 @@ from .filters import (
|
|||
)
|
||||
from .renderers import WagtailJSONRenderer
|
||||
from .pagination import WagtailPagination
|
||||
from .serializers import WagtailSerializer, PageSerializer, DocumentSerializer
|
||||
from .serializers import BaseSerializer, PageSerializer, DocumentSerializer, get_serializer_class
|
||||
from .utils import BadRequestError
|
||||
|
||||
|
||||
class BaseAPIEndpoint(GenericViewSet):
|
||||
renderer_classes = [WagtailJSONRenderer]
|
||||
pagination_class = WagtailPagination
|
||||
serializer_class = WagtailSerializer
|
||||
base_serializer_class = BaseSerializer
|
||||
filter_classes = []
|
||||
queryset = None # Set on subclasses or implement `get_queryset()`.
|
||||
|
||||
|
|
@ -87,18 +87,21 @@ class BaseAPIEndpoint(GenericViewSet):
|
|||
if unknown_parameters:
|
||||
raise BadRequestError("query parameter is not an operation or a recognised field: %s" % ', '.join(sorted(unknown_parameters)))
|
||||
|
||||
def get_serializer_context(self):
|
||||
"""
|
||||
The serialization context differs between listing and detail views.
|
||||
"""
|
||||
def get_serializer_class(self):
|
||||
request = self.request
|
||||
|
||||
# Get model
|
||||
if self.action == 'listing_view':
|
||||
model = self.get_queryset().model
|
||||
else:
|
||||
model = type(self.get_object())
|
||||
|
||||
all_fields = self.get_api_fields(model)
|
||||
all_fields = list(OrderedDict.fromkeys(all_fields)) # Removes any duplicates in case the developer put "title" in api_fields
|
||||
# Get all available fields
|
||||
all_fields = self.get_api_fields(model)
|
||||
all_fields = list(OrderedDict.fromkeys(all_fields)) # Removes any duplicates in case the developer put "title" in api_fields
|
||||
|
||||
if self.action == 'listing_view':
|
||||
# Listing views just show the title field and any other allowed field the user specified
|
||||
if 'fields' in request.GET:
|
||||
fields = set(request.GET['fields'].split(','))
|
||||
else:
|
||||
|
|
@ -111,22 +114,27 @@ class BaseAPIEndpoint(GenericViewSet):
|
|||
|
||||
# Reorder fields so it matches the order of all_fields
|
||||
fields = [field for field in all_fields if field in fields]
|
||||
else:
|
||||
# Detail views show all fields all the time
|
||||
fields = all_fields
|
||||
|
||||
return get_serializer_class(model, fields, base=self.base_serializer_class)
|
||||
|
||||
def get_serializer_context(self):
|
||||
"""
|
||||
The serialization context differs between listing and detail views.
|
||||
"""
|
||||
request = self.request
|
||||
|
||||
if self.action == 'listing_view':
|
||||
return {
|
||||
'request': request,
|
||||
'view': self,
|
||||
'fields': fields
|
||||
}
|
||||
|
||||
model = type(self.get_object())
|
||||
|
||||
all_fields = self.get_api_fields(model)
|
||||
all_fields = list(OrderedDict.fromkeys(all_fields)) # Removes any duplicates in case the developer put "title" in api_fields
|
||||
|
||||
return {
|
||||
'request': request,
|
||||
'view': self,
|
||||
'fields': all_fields,
|
||||
'show_details': True
|
||||
}
|
||||
|
||||
|
|
@ -155,7 +163,7 @@ class BaseAPIEndpoint(GenericViewSet):
|
|||
|
||||
|
||||
class PagesAPIEndpoint(BaseAPIEndpoint):
|
||||
serializer_class = PageSerializer
|
||||
base_serializer_class = PageSerializer
|
||||
filter_backends = [
|
||||
FieldsFilter,
|
||||
ChildOfFilter,
|
||||
|
|
@ -216,7 +224,7 @@ class ImagesAPIEndpoint(BaseAPIEndpoint):
|
|||
|
||||
class DocumentsAPIEndpoint(BaseAPIEndpoint):
|
||||
queryset = Document.objects.all().order_by('id')
|
||||
serializer_class = DocumentSerializer
|
||||
base_serializer_class = DocumentSerializer
|
||||
filter_backends = [FieldsFilter, OrderingFilter, SearchFilter]
|
||||
extra_api_fields = ['title', 'tags']
|
||||
name = 'documents'
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ from wagtail.utils.compat import get_related_model
|
|||
from wagtail.wagtailcore.models import Page
|
||||
from wagtail.wagtailcore import fields as wagtailcore_fields
|
||||
|
||||
from .utils import ObjectDetailURL, URLPath, BadRequestError, pages_for_site
|
||||
from .utils import ObjectDetailURL, URLPath, pages_for_site
|
||||
|
||||
|
||||
class ChildRelationField(Field):
|
||||
|
|
@ -27,7 +27,8 @@ class ChildRelationField(Field):
|
|||
serializer = serializer_class()
|
||||
|
||||
return [
|
||||
serializer.to_representation(child_object)
|
||||
# Use rest frameworks to_representation method so we don't add id/meta attributes
|
||||
super(BaseSerializer, serializer).to_representation(child_object)
|
||||
for child_object in value.all()
|
||||
]
|
||||
|
||||
|
|
@ -88,24 +89,8 @@ class BaseSerializer(serializers.ModelSerializer):
|
|||
|
||||
return super(BaseSerializer, self).build_relational_field(field_name, relation_info)
|
||||
|
||||
|
||||
def get_serializer_class(model_, fields_):
|
||||
class Meta:
|
||||
model = model_
|
||||
fields = fields_
|
||||
|
||||
return type(model_.__name__ + 'Serializer', (BaseSerializer, ), {
|
||||
'Meta': Meta
|
||||
})
|
||||
|
||||
|
||||
class WagtailSerializer(serializers.BaseSerializer):
|
||||
def to_representation(self, instance):
|
||||
fields = self.context.get('fields')
|
||||
return self.serialize_object(
|
||||
instance,
|
||||
fields=fields,
|
||||
)
|
||||
return self.serialize_object(instance)
|
||||
|
||||
def serialize_object_metadata(self, obj):
|
||||
"""
|
||||
|
|
@ -120,7 +105,7 @@ class WagtailSerializer(serializers.BaseSerializer):
|
|||
|
||||
return data
|
||||
|
||||
def serialize_object(self, obj, fields, extra_data=()):
|
||||
def serialize_object(self, obj, extra_data=()):
|
||||
"""
|
||||
This converts an object into JSON-serialisable dict so it can
|
||||
be used in the API.
|
||||
|
|
@ -138,14 +123,12 @@ class WagtailSerializer(serializers.BaseSerializer):
|
|||
data.extend(extra_data)
|
||||
|
||||
# Serialize the fields
|
||||
serializer_class = get_serializer_class(type(obj), fields)
|
||||
serializer = serializer_class()
|
||||
data.extend(serializer.to_representation(obj).items())
|
||||
data.extend(super(BaseSerializer, self).to_representation(obj).items())
|
||||
|
||||
return OrderedDict(data)
|
||||
|
||||
|
||||
class PageSerializer(WagtailSerializer):
|
||||
class PageSerializer(BaseSerializer):
|
||||
def serialize_object_metadata(self, page):
|
||||
data = super(PageSerializer, self).serialize_object_metadata(page)
|
||||
|
||||
|
|
@ -154,7 +137,7 @@ class PageSerializer(WagtailSerializer):
|
|||
|
||||
return data
|
||||
|
||||
def serialize_object(self, page, fields, extra_data=()):
|
||||
def serialize_object(self, page, extra_data=()):
|
||||
# Add parent
|
||||
if self.context.get('show_details', False):
|
||||
parent = page.get_parent()
|
||||
|
|
@ -173,10 +156,10 @@ class PageSerializer(WagtailSerializer):
|
|||
])),
|
||||
)
|
||||
|
||||
return super(PageSerializer, self).serialize_object(page, fields, extra_data=extra_data)
|
||||
return super(PageSerializer, self).serialize_object(page, extra_data=extra_data)
|
||||
|
||||
|
||||
class DocumentSerializer(WagtailSerializer):
|
||||
class DocumentSerializer(BaseSerializer):
|
||||
def serialize_object_metadata(self, document):
|
||||
data = super(DocumentSerializer, self).serialize_object_metadata(document)
|
||||
|
||||
|
|
@ -185,3 +168,13 @@ class DocumentSerializer(WagtailSerializer):
|
|||
data['download_url'] = URLPath(document.url)
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def get_serializer_class(model_, fields_, base=BaseSerializer):
|
||||
class Meta:
|
||||
model = model_
|
||||
fields = fields_
|
||||
|
||||
return type(model_.__name__ + 'Serializer', (base, ), {
|
||||
'Meta': Meta
|
||||
})
|
||||
|
|
|
|||
Loading…
Reference in a new issue