Commit 5ce49f46 authored by Jean-Baptiste's avatar Jean-Baptiste

update: split serializer (read / write)

parent 02cb2a21
from django.db.models import options from django.db.models import options
__version__ = '0.0.0' __version__ = '0.0.0'
options.DEFAULT_NAMES += ('lookup_field', 'rdf_type', 'rdf_context', 'auto_author', 'view_set', 'container_path', 'permission_classes', 'serializer_fields', 'nested_fields', 'depth', 'many_depth') options.DEFAULT_NAMES += ('lookup_field', 'rdf_type', 'rdf_context', 'auto_author', 'view_set', 'container_path', 'permission_classes', 'serializer_fields', 'nested_fields', 'depth')
\ No newline at end of file
...@@ -66,7 +66,6 @@ class Model(models.Model): ...@@ -66,7 +66,6 @@ class Model(models.Model):
default_permissions = ('add', 'change', 'delete', 'view', 'control') default_permissions = ('add', 'change', 'delete', 'view', 'control')
abstract = True abstract = True
depth = 1 depth = 1
many_depth = 0
@classonlymethod @classonlymethod
def resolve_id(cls, id): def resolve_id(cls, id):
......
...@@ -258,8 +258,7 @@ class LDPSerializer(HyperlinkedModelSerializer): ...@@ -258,8 +258,7 @@ class LDPSerializer(HyperlinkedModelSerializer):
nested_fields=Model.get_meta(model_class, 'nested_fields', [])) nested_fields=Model.get_meta(model_class, 'nested_fields', []))
parent_depth = max(getattr(self.parent.Meta, "depth", 0) - 1, 0) parent_depth = max(getattr(self.parent.Meta, "depth", 0) - 1, 0)
serializer_generator.depth = parent_depth serializer_generator.depth = parent_depth
serializer_generator.many_depth = max(getattr(self.parent.Meta, "many_depth", 0) - 1, 0) serializer = serializer_generator.build_read_serializer()(context=self.parent.context)
serializer = serializer_generator.build_serializer()(context=self.parent.context)
if parent_depth is 0: if parent_depth is 0:
serializer.Meta.fields = ["@id"] serializer.Meta.fields = ["@id"]
return {'@id': '{}{}{}/'.format(settings.SITE_URL, '{}{}/', self.source), return {'@id': '{}{}{}/'.format(settings.SITE_URL, '{}{}/', self.source),
...@@ -405,7 +404,7 @@ class LDPSerializer(HyperlinkedModelSerializer): ...@@ -405,7 +404,7 @@ class LDPSerializer(HyperlinkedModelSerializer):
def many_init(cls, *args, **kwargs): def many_init(cls, *args, **kwargs):
kwargs['child'] = cls(**kwargs) kwargs['child'] = cls(**kwargs)
try: try:
cls.Meta.depth = cls.compute_depth(kwargs['context']['view'].many_depth, cls.Meta.model, 'many_depth') cls.Meta.depth = cls.compute_depth(kwargs['context']['view'].depth, cls.Meta.model, 'depth')
except KeyError: except KeyError:
pass pass
return ContainerSerializer(*args, **kwargs) return ContainerSerializer(*args, **kwargs)
......
...@@ -63,7 +63,7 @@ failures = test_runner.run_tests([ ...@@ -63,7 +63,7 @@ failures = test_runner.run_tests([
'djangoldp.tests.tests_auto_author', 'djangoldp.tests.tests_auto_author',
'djangoldp.tests.tests_get', 'djangoldp.tests.tests_get',
'djangoldp.tests.tests_delete', 'djangoldp.tests.tests_delete',
# 'djangoldp.tests.tests_temp' 'djangoldp.tests.tests_temp'
]) ])
if failures: if failures:
......
...@@ -18,3 +18,4 @@ class TestTemp(TestCase): ...@@ -18,3 +18,4 @@ class TestTemp(TestCase):
pass pass
...@@ -281,8 +281,8 @@ class Update(TestCase): ...@@ -281,8 +281,8 @@ class Update(TestCase):
{ {
'@id': "_:b975", '@id': "_:b975",
'http://happy-dev.fr/owl/#description': "user description", 'http://happy-dev.fr/owl/#description': "user description",
'http://happy-dev.fr/owl/#dummy': { 'http://happy-dev.fr/owl/#dummy': {
'@id' : './' '@id': './'
} }
}, },
{ {
...@@ -366,7 +366,8 @@ class Update(TestCase): ...@@ -366,7 +366,8 @@ class Update(TestCase):
def test_missing_field_should_not_be_removed_with_fk_relation(self): def test_missing_field_should_not_be_removed_with_fk_relation(self):
user = User.objects.create(username="alex", password="test") user = User.objects.create(username="alex", password="test")
peer = User.objects.create(username="sylvain", password="test2") peer = User.objects.create(username="sylvain", password="test2")
conversation = Conversation.objects.create(author_user=user, peer_user=peer, description="conversation description") conversation = Conversation.objects.create(author_user=user, peer_user=peer,
description="conversation description")
body = [ body = [
{ {
'@id': "/conversations/{}/".format(conversation.pk), '@id': "/conversations/{}/".format(conversation.pk),
...@@ -381,7 +382,8 @@ class Update(TestCase): ...@@ -381,7 +382,8 @@ class Update(TestCase):
def test_empty_field_should_be_removed_with_fk_relation(self): def test_empty_field_should_be_removed_with_fk_relation(self):
user = User.objects.create(username="alex", password="test") user = User.objects.create(username="alex", password="test")
peer = User.objects.create(username="sylvain", password="test2") peer = User.objects.create(username="sylvain", password="test2")
conversation = Conversation.objects.create(author_user=user, peer_user=peer, description="conversation description") conversation = Conversation.objects.create(author_user=user, peer_user=peer,
description="conversation description")
body = [ body = [
{ {
'@id': "/conversations/{}/".format(conversation.pk), '@id': "/conversations/{}/".format(conversation.pk),
...@@ -393,4 +395,3 @@ class Update(TestCase): ...@@ -393,4 +395,3 @@ class Update(TestCase):
content_type='application/ld+json') content_type='application/ld+json')
self.assertEqual(response.status_code, 200) self.assertEqual(response.status_code, 200)
self.assertEqual(response.data['peer_user'], None) self.assertEqual(response.data['peer_user'], None)
...@@ -9,10 +9,13 @@ from django.shortcuts import get_object_or_404 ...@@ -9,10 +9,13 @@ from django.shortcuts import get_object_or_404
from django.utils.decorators import classonlymethod from django.utils.decorators import classonlymethod
from guardian.shortcuts import get_objects_for_user from guardian.shortcuts import get_objects_for_user
from pyld import jsonld from pyld import jsonld
from rest_framework import status
from rest_framework.authentication import SessionAuthentication from rest_framework.authentication import SessionAuthentication
from rest_framework.parsers import JSONParser from rest_framework.parsers import JSONParser
from rest_framework.renderers import JSONRenderer from rest_framework.renderers import JSONRenderer
from rest_framework.viewsets import ModelViewSet from rest_framework.viewsets import ModelViewSet
from rest_framework.response import Response
from djangoldp.models import LDPSource, Model from djangoldp.models import LDPSource, Model
...@@ -90,8 +93,7 @@ class LDPViewSet(LDPViewSetGenerator): ...@@ -90,8 +93,7 @@ class LDPViewSet(LDPViewSetGenerator):
"""An automatically generated viewset that serves models following the Linked Data Platform convention""" """An automatically generated viewset that serves models following the Linked Data Platform convention"""
fields = None fields = None
exclude = None exclude = None
depth = 2 depth = 1
many_depth = 1
renderer_classes = (JSONLDRenderer,) renderer_classes = (JSONLDRenderer,)
parser_classes = (JSONLDParser,) parser_classes = (JSONLDParser,)
authentication_classes = (NoCSRFAuthentication,) authentication_classes = (NoCSRFAuthentication,)
...@@ -103,22 +105,69 @@ class LDPViewSet(LDPViewSetGenerator): ...@@ -103,22 +105,69 @@ class LDPViewSet(LDPViewSetGenerator):
if hasattr(p, 'filter_class') and p.filter_class: if hasattr(p, 'filter_class') and p.filter_class:
self.filter_backends = p.filter_class self.filter_backends = p.filter_class
self.serializer_class = self.build_serializer() self.serializer_class = self.build_read_serializer()
self.write_serializer_class = self.build_write_serializer()
def build_serializer(self): def build_read_serializer(self):
model_name = self.model._meta.object_name.lower() model_name = self.model._meta.object_name.lower()
lookup_field = get_resolver().reverse_dict[model_name + '-detail'][0][0][1][0] lookup_field = get_resolver().reverse_dict[model_name + '-detail'][0][0][1][0]
meta_args = {'model': self.model, 'extra_kwargs': { meta_args = {'model': self.model, 'extra_kwargs': {
'@id': {'lookup_field': lookup_field}}, '@id': {'lookup_field': lookup_field}},
'depth': self.depth, 'depth': self.depth,
'extra_fields': self.nested_fields} 'extra_fields': self.nested_fields}
return self.build_serializer(meta_args, 'Read')
def build_write_serializer(self):
model_name = self.model._meta.object_name.lower()
lookup_field = get_resolver().reverse_dict[model_name + '-detail'][0][0][1][0]
meta_args = {'model': self.model, 'extra_kwargs': {
'@id': {'lookup_field': lookup_field}},
'depth': 10,
'extra_fields': self.nested_fields}
return self.build_serializer(meta_args, 'Write')
def build_serializer(self, meta_args, name_prefix):
if self.fields: if self.fields:
meta_args['fields'] = self.fields meta_args['fields'] = self.fields
else: else:
meta_args['exclude'] = self.exclude or () meta_args['exclude'] = self.exclude or ()
meta_class = type('Meta', (), meta_args) meta_class = type('Meta', (), meta_args)
from djangoldp.serializers import LDPSerializer from djangoldp.serializers import LDPSerializer
return type(LDPSerializer)(model_name + 'Serializer', (LDPSerializer,), {'Meta': meta_class}) return type(LDPSerializer)(self.model._meta.object_name.lower() + name_prefix + 'Serializer', (LDPSerializer,), {'Meta': meta_class})
def create(self, request, *args, **kwargs):
serializer = self.get_write_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
def get_write_serializer(self, *args, **kwargs):
"""
Return the serializer instance that should be used for validating and
deserializing input, and for serializing output.
"""
serializer_class = self.get_write_serializer_class()
kwargs['context'] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
def get_write_serializer_class(self):
"""
Return the class to use for the serializer.
Defaults to using `self.write_serializer_class`.
You may want to override this if you need to provide different
serializations depending on the incoming request.
(Eg. admins get full serialization, others get basic serialization)
"""
assert self.write_serializer_class is not None, (
"'%s' should either include a `write_serializer_class` attribute, "
"or override the `get_write_serializer_class()` method."
% self.__class__.__name__
)
return self.write_serializer_class
def perform_create(self, serializer, **kwargs): def perform_create(self, serializer, **kwargs):
if hasattr(self.model._meta, 'auto_author') and isinstance(self.request.user, get_user_model()): if hasattr(self.model._meta, 'auto_author') and isinstance(self.request.user, get_user_model()):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment