Skip to content
This repository was archived by the owner on Aug 11, 2021. It is now read-only.

Developer's Guide

MisterNando edited this page Jun 22, 2014 · 44 revisions

Introduction

The OCL API is implemented as a series of modifications to the Django REST Framework. These modifications were necessary to allow for the nesting of resources, and are outlined below. This guide is intended to be used as a supplement to the Django REST Framework Quickstart Guide, and is structured in the same fashion.

Serializers

Most CREATE and UPDATE serializers are implemented as standard rest_framework.serializers.Serializer classes. For these operations, the list of fields specified in the class definition describes the set of fields that may be set (or modified) by the corresponding operation. For most resource types, some subset of fields will be unmodifiable, so the UPDATE view will be distinct from the CREATE view. For example, consider:

class OrganizationUpdateSerializer(serializers.Serializer):
    name = serializers.CharField(required=False)
    company = serializers.CharField(required=False)
    website = serializers.CharField(required=False)

which is distinct from:

class OrganizationCreateSerializer(serializers.Serializer):
    id = serializers.CharField(required=True, validators=[RegexValidator(regex=NAMESPACE_REGEX)], source='mnemonic')
    name = serializers.CharField(required=True)
    company = serializers.CharField(required=False)
    website = serializers.CharField(required=False)

because the id field is unmodifiable.

HyperlinkedResourceSerializer

The next most-widely used serializer is the homegrown oclapi.serializers.HyperlinkedResourceSerializer. It is nearly identical to the REST Framework's rest_framework.serializers.HyperlinkedModelSerializer, except that it uses a different field type to render the identity ('url') field.

class HyperlinkedModelSerializer(ModelSerializer):
    ...
    def get_default_fields(self):
        fields = super(HyperlinkedModelSerializer, self).get_default_fields()

        if self.opts.view_name is None:
            self.opts.view_name = self._get_default_view_name(self.opts.model)

        if 'url' not in fields:
            url_field = HyperlinkedIdentityField(
                view_name=self.opts.view_name,
                lookup_field=self.opts.lookup_field
            )
            ret = self._dict_class()
            ret['url'] = url_field
            ret.update(fields)
            fields = ret

    return fields

Note that the HyperlinkedModelSerializer uses the REST Framework's rest_framework.relations.HyperlinkedIdentityField to render its 'url' field. This field type merely uses django.core.urlresolvers.reverse to generate a URL for the object in question, but this implementation of reversedoes not account for the nested of resources.

HyperlinkedResourceSerializer instead uses a HyperlinkedResourceIdentifyField:

class HyperlinkedResourceSerializer(serializers.Serializer):
    ...
    def get_default_fields(self):
        fields = super(HyperlinkedResourceSerializer, self).get_default_fields()

        if self.opts.view_name is None:
            self.opts.view_name = self._get_default_view_name(self.opts.model)

        if 'url' not in fields:
            url_field = HyperlinkedResourceIdentityField(
                view_name=self.opts.view_name,
            )
            ret = self._dict_class()
            ret['url'] = url_field
            ret.update(fields)
            fields = ret

    return fields

HyperlinkedResourceIdentityField uses oclapi.utils.reverse_resource to generate the resource URL, which, unlike django.core.urlresolvers.reverse, does account for resource nesting.

The OrganizationDetailSerializer is an example of a HyperlinkedResourceSerializer:

class OrganizationDetailSerializer(HyperlinkedResourceSerializer):
    type = serializers.CharField(source='resource_type')
    uuid = serializers.CharField(source='id')
    id = serializers.CharField(source='mnemonic')
    name = serializers.CharField()
    company = serializers.CharField()
    website = serializers.CharField()
    members = serializers.IntegerField(source='num_members')
    publicSources = serializers.IntegerField(source='public_sources')
    createdOn = serializers.DateTimeField(source='created_at')
    updatedOn = serializers.DateTimeField(source='updated_at')

So, in addition to the fields listed above, OrganizationDetailSerializer will use HyperlinkedResourceIdentityField (which uses oclapi.utils.reverse_resource) to render the resource URL for the organization in question.

Clone this wiki locally