Commit 9be36e48 authored by Calum Mackervoy's avatar Calum Mackervoy

more comments in serializers and views

parent 9addce37
Pipeline #7198 passed with stage
in 1 minute and 20 seconds
......@@ -27,13 +27,17 @@ from djangoldp.permissions import LDPPermissions
class LDListMixin:
'''A Mixin used by the custom Serializers in this file'''
child_attr = 'child'
# converts primitive data representation to the representation used within our application
def to_internal_value(self, data):
try:
# if this is a container, the data will be stored in ldp:contains
data = data['ldp:contains']
except (TypeError, KeyError):
pass
if len(data) == 0:
return []
if isinstance(data, dict):
......@@ -43,6 +47,7 @@ class LDListMixin:
return [getattr(self, self.child_attr).to_internal_value(item) for item in data]
# converts internal representation to primitive data representation
def to_representation(self, value):
'''
Permission on container :
......@@ -53,7 +58,9 @@ class LDListMixin:
child_model = getattr(self, self.child_attr).Meta.model
except AttributeError:
child_model = value.model
parent_model = None
if isinstance(value, QuerySet):
value = list(value)
......@@ -61,11 +68,13 @@ class LDListMixin:
filtered_values = value
container_permissions = Model.get_permissions(child_model, self.context['request'].user, ['view', 'add'])
else:
# this is a container. Parent model is the containing object, child the model contained
try:
parent_model = Model.resolve_parent(self.context['request'].path)
except:
parent_model = child_model
# remove objects from the list which I don't have permission to view
filtered_values = list(
filter(lambda v: Model.get_permission_classes(v, [LDPPermissions])[0]().has_object_permission(
self.context['request'], self.context['view'], v), value))
......
......@@ -24,6 +24,8 @@ from djangoldp.permissions import LDPPermissions
get_user_model()._meta.rdf_context = {"get_full_name": "rdfs:label"}
# renders into JSONLD format by applying context to the data
# https://github.com/digitalbazaar/pyld
class JSONLDRenderer(JSONRenderer):
media_type = 'application/ld+json'
......@@ -38,15 +40,18 @@ class JSONLDRenderer(JSONRenderer):
data["@context"] = settings.LDP_RDF_CONTEXT
return super(JSONLDRenderer, self).render(data, accepted_media_type, renderer_context)
# https://github.com/digitalbazaar/pyld
class JSONLDParser(JSONParser):
media_type = 'application/ld+json'
def parse(self, stream, media_type=None, parser_context=None):
data = super(JSONLDParser, self).parse(stream, media_type, parser_context)
# compact applies the context to the data and makes it a format which is easier to work with
# see: http://json-ld.org/spec/latest/json-ld/#compacted-document-form
return jsonld.compact(data, ctx=settings.LDP_RDF_CONTEXT)
# an authentication class which exempts CSRF authentication
class NoCSRFAuthentication(SessionAuthentication):
def enforce_csrf(self, request):
return
......@@ -81,6 +86,7 @@ class LDPViewSetGenerator(ModelViewSet):
@classonlymethod
def urls(cls, **kwargs):
'''constructs urls list for model passed in kwargs'''
kwargs['model'] = cls.get_model(**kwargs)
model_name = kwargs['model']._meta.object_name.lower()
if kwargs.get('model_prefix'):
......@@ -93,12 +99,14 @@ class LDPViewSetGenerator(ModelViewSet):
name='{}-detail'.format(model_name)),
]
# append nested fields to the urls list
for field in kwargs.get('nested_fields') or cls.nested_fields:
urls.append(url('^' + detail_expr + field + '/', LDPNestedViewSet.nested_urls(field, **kwargs)))
return include(urls)
# LDPViewSetGenerator is a ModelViewSet (DRF) with methods to automatically generate model urls
class LDPViewSet(LDPViewSetGenerator):
"""An automatically generated viewset that serves models following the Linked Data Platform convention"""
fields = None
......@@ -109,6 +117,8 @@ class LDPViewSet(LDPViewSetGenerator):
def __init__(self, **kwargs):
super().__init__(**kwargs)
# attach filter backends based on permissions classes, to reduce the queryset based on these permissions
# https://www.django-rest-framework.org/api-guide/filtering/#generic-filtering
if self.permission_classes:
for p in self.permission_classes:
if hasattr(p, 'filter_class') and p.filter_class:
......@@ -136,11 +146,13 @@ class LDPViewSet(LDPViewSetGenerator):
return self.build_serializer(meta_args, 'Write')
def build_serializer(self, meta_args, name_prefix):
# create the Meta class to associate to LDPSerializer, using meta_args param
if self.fields:
meta_args['fields'] = self.fields
else:
meta_args['exclude'] = self.exclude or ()
meta_class = type('Meta', (), meta_args)
from djangoldp.serializers import LDPSerializer
return type(LDPSerializer)(self.model._meta.object_name.lower() + name_prefix + 'Serializer', (LDPSerializer,),
{'Meta': meta_class})
......@@ -148,6 +160,7 @@ class LDPViewSet(LDPViewSetGenerator):
def create(self, request, *args, **kwargs):
serializer = self.get_write_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
response_serializer = self.get_serializer()
data = response_serializer.to_representation(serializer.instance)
......@@ -210,6 +223,7 @@ class LDPViewSet(LDPViewSetGenerator):
return super(LDPView, self).get_queryset(*args, **kwargs)
def dispatch(self, request, *args, **kwargs):
'''overriden dispatch method to append some custom headers'''
response = super(LDPViewSet, self).dispatch(request, *args, **kwargs)
response["Access-Control-Allow-Origin"] = request.META.get('HTTP_ORIGIN')
response["Access-Control-Allow-Methods"] = "GET,POST,PUT,PATCH,DELETE"
......
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