From 963dc3c62df8457a64492b15aeba03b71e97009e Mon Sep 17 00:00:00 2001 From: Tom Hacohen Date: Wed, 15 Apr 2020 15:23:07 +0300 Subject: [PATCH] Cleanup how we handle inline serializers. --- django_etesync/serializers.py | 42 ++++++++++++++++++----------------- django_etesync/views.py | 23 +++++++++++-------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/django_etesync/serializers.py b/django_etesync/serializers.py index 2310c8d..6a495bf 100644 --- a/django_etesync/serializers.py +++ b/django_etesync/serializers.py @@ -66,44 +66,40 @@ class CollectionItemChunkSerializer(serializers.ModelSerializer): fields = ('uid', 'chunkFile') -class CollectionItemRevisionBaseSerializer(serializers.ModelSerializer): +class CollectionItemRevisionSerializer(serializers.ModelSerializer): chunks = serializers.SlugRelatedField( slug_field='uid', queryset=models.CollectionItemChunk.objects.all(), many=True ) + chunksUrls = serializers.SerializerMethodField('get_chunks_urls') + chunksData = serializers.SerializerMethodField('get_chunks_data') meta = BinaryBase64Field() class Meta: model = models.CollectionItemRevision - fields = ('chunks', 'meta', 'uid', 'deleted') - - -class CollectionItemRevisionSerializer(CollectionItemRevisionBaseSerializer): - chunksUrls = serializers.SerializerMethodField('get_chunks_urls') - - class Meta(CollectionItemRevisionBaseSerializer.Meta): - fields = CollectionItemRevisionBaseSerializer.Meta.fields + ('chunksUrls', ) + fields = ('chunks', 'meta', 'uid', 'deleted', 'chunksUrls', 'chunksData') # FIXME: currently the user is exposed in the url. We don't want that, and we can probably avoid that but still # save it under the user. # We would probably be better off just let the user calculate the urls from the uid and a base url for the snapshot. # E.g. chunkBaseUrl: "/media/bla/bla/" or chunkBaseUrl: "https://media.etesync.com/bla/bla" def get_chunks_urls(self, obj): + prefer_inline = self.context.get('prefer_inline', False) + if prefer_inline: + return None + ret = [] for chunk in obj.chunks.all(): ret.append(chunk.chunkFile.url) return ret - -class CollectionItemRevisionInlineSerializer(CollectionItemRevisionBaseSerializer): - chunksData = serializers.SerializerMethodField('get_chunks_data') - - class Meta(CollectionItemRevisionBaseSerializer.Meta): - fields = CollectionItemRevisionBaseSerializer.Meta.fields + ('chunksData', ) - def get_chunks_data(self, obj): + prefer_inline = self.context.get('prefer_inline', False) + if not prefer_inline: + return None + ret = [] for chunk in obj.chunks.all(): with open(chunk.chunkFile.path, 'rb') as f: @@ -111,6 +107,16 @@ class CollectionItemRevisionInlineSerializer(CollectionItemRevisionBaseSerialize return ret + def to_representation(self, instance): + ret = super().to_representation(instance) + prefer_inline = self.context.get('prefer_inline', False) + if prefer_inline: + ret.pop('chunksUrls') + else: + ret.pop('chunksData') + + return ret + class CollectionItemSerializer(serializers.ModelSerializer): encryptionKey = BinaryBase64Field() @@ -154,10 +160,6 @@ class CollectionItemSerializer(serializers.ModelSerializer): return instance -class CollectionItemInlineSerializer(CollectionItemSerializer): - content = CollectionItemRevisionInlineSerializer(read_only=True, many=False) - - class CollectionSerializer(serializers.ModelSerializer): encryptionKey = CollectionEncryptionKeyField() accessLevel = serializers.SerializerMethodField('get_access_level_from_context') diff --git a/django_etesync/views.py b/django_etesync/views.py index a4b8108..37de4bb 100644 --- a/django_etesync/views.py +++ b/django_etesync/views.py @@ -29,7 +29,6 @@ from .models import Collection, CollectionItem from .serializers import ( CollectionSerializer, CollectionItemSerializer, - CollectionItemInlineSerializer, CollectionItemRevisionSerializer, CollectionItemChunkSerializer ) @@ -66,12 +65,18 @@ class CollectionViewSet(BaseViewSet): queryset = type(self).queryset return self.get_collection_queryset(queryset) + def get_serializer_context(self): + context = super().get_serializer_context() + prefer_inline = self.request.method == 'GET' and 'prefer_inline' in self.request.query_params + context.update({'request': self.request, 'prefer_inline': prefer_inline}) + return context + def destroy(self, request, uid=None): # FIXME: implement return Response(status=status.HTTP_405_METHOD_NOT_ALLOWED) def create(self, request, *args, **kwargs): - serializer = self.serializer_class(data=request.data) + serializer = self.serializer_class(data=request.data, context=self.get_serializer_context()) if serializer.is_valid(): try: serializer.save(owner=self.request.user) @@ -86,7 +91,7 @@ class CollectionViewSet(BaseViewSet): def list(self, request): queryset = self.get_queryset() - serializer = self.serializer_class(queryset, context={'request': request}, many=True) + serializer = self.serializer_class(queryset, context=self.get_serializer_context(), many=True) return Response(serializer.data) @@ -98,12 +103,6 @@ class CollectionItemViewSet(BaseViewSet): pagination_class = paginators.LinkHeaderPagination lookup_field = 'uid' - def get_serializer_class(self): - if self.request.method == 'GET' and self.request.query_params.get('prefer_inline'): - return CollectionItemInlineSerializer - - return super().get_serializer_class() - def get_queryset(self): collection_uid = self.kwargs['collection_uid'] try: @@ -117,6 +116,12 @@ class CollectionItemViewSet(BaseViewSet): return queryset + def get_serializer_context(self): + context = super().get_serializer_context() + prefer_inline = self.request.method == 'GET' and 'prefer_inline' in self.request.query_params + context.update({'request': self.request, 'prefer_inline': prefer_inline}) + return context + def create(self, request, collection_uid=None): collection_object = get_object_or_404(self.get_collection_queryset(Collection.objects), uid=collection_uid)