Extension for Django REST Framework 3 which allows for using content-type application/hal-json.
This fork of https://github.com/seebass/drf-hal-json is under active development. As soon as there is a stable version ready, we'll do a merge and push a PyPI package. Until then this should not be considered stable.
pip install drf-hal-json
REST_FRAMEWORK = {
'DEFAULT_PAGINATION_CLASS': 'drf_hal_json.pagination.HalPageNumberPagination',
'DEFAULT_PARSER_CLASSES': ('drf_hal_json.parsers.JsonHalParser',),
'DEFAULT_RENDERER_CLASSES': (
'drf_hal_json.renderers.JsonHalRenderer',
'rest_framework.renderers.BrowsableAPIRenderer',
),
# To make self links render as 'self' and not 'url', as per the HAL spec
'URL_FIELD_NAME': 'self',
}
- Python 3.5+
- Django 1.11+
- Django REST Framework 3
By using the HalModelSerializer the content is serialized in the HAL JSON format.
Pagination is supported and will produce next and previous links.
Model-level relations are both _linked and _embedded per default. For only
linking, use HalHyperlinkedRelatedField in the serializer.
Serializer:
class ResourceSerializer(HalModelSerializer):
class Meta:
model = ResourceView:
class ResourceViewSet(HalCreateModelMixin, ModelViewSet):
serializer_class = ResourceSerializer
queryset = Resource.objects.all()Request:
GET http://localhost/api/resources/1/ HTTP/1.1
Content-Type application/hal+json
{
"_links": {
"self": {"href": "http://localhost/api/resources/1/"},
"relatedResource": {"href": "http://localhost/api/related-resources/1/"}
},
"id": 1,
"_embedded": {
"subResource": {
"_links": {
"self": {"href": "http://localhost/resources/1/sub-resources/26/"},
"subSubResource": {"href": "http://localhost/resources/1/sub-resources/26/sub-sub-resources/3"}
},
"id": 26,
"name": "Sub Resource 26"
}
}
}
The HAL spec defines a number of optional link properties, such as title.
These are supported in two different ways.
If the link relationship is based on a model-layer relationship, you can use
HalHyperlinkedRelatedField, which supports a number of additional keyword
parameters, corresponding to the optional link properties in the HAL specification:
from drf_hal_json.fields import HalHyperlinkedRelatedField
class Resource1Serializer(HalModelSerializer):
# when using HalHyperlinkedRelatedField, the related resources
# will not be embedded, just linked.
related_resources = HalHyperlinkedRelatedField(
many=True, read_only=True, view_name='relatedresource-detail',
title_field='name') # .. also type_field, templated_field, etc.
class Meta:
model = Resource1
fields = ('self', 'related_resources')The above will look up the name field of the each related resource and
use that as the link title.
There is also a HalHyperlinkedIdentityField which behaves in the same way.
The other way to add custom properties to a link relation is to use
HalContributeToLinkField. This requires a serializer method to be
added.
from drf_hal_json.fields import HalContributeToLinkField
class FileSerializer(HalModelSerializer):
file = HalFileField()
file_title = HalContributeToLinkField(place_on='file')
file_type = HalContributeToLinkField(place_on='file', property_name='type')
class Meta:
model = FileResource
fields = ('file', 'file_title', 'file_type')
def get_file_title(self, obj):
return str(obj.pk)
def get_file_type(self, obj):
return 'application/zip'See the implementation of HalFileField to see how a URL-producing
serializer (by default FileField serializes to a URL) can be included
in _links.
HalContributeToLinkField can be used for any model-level relation
which are not explicitly linked using HalHyperlinkedRelatedField.
In this case, HalContributeToLinkField can be used to adorn the self
relation of the resource that is linked to with additional properties.
If you need to process a link URL, or need to insert a URL that is
completely separate from whatever model you are serializing, the
HalHyperlinkedPropertyField can be used.
from drf_hal_json.fields import HalHyperlinkedPropertyField
class ResourceWithUrl(Model):
@property
def get_docs_url(self):
return '/docs/foo'
@property
def external_url(self):
return 'http://example.com/'
class CustomSerializer(HalModelSerializer):
docs_url = HalHyperlinkedPropertyField(
source='get_docs_url',
process_value=lambda val: val + '?bar')
external_url = HalHyperlinkedPropertyField()
class Meta:
model = ResourceWithUrl
fields = ('self', 'docs_url', 'external_url')This will serialize into:
{
"_links": {
"docs_url": {
"href": "http://localhost/docs/foo?bar"
},
"external_url": {
"href": "http://example.com/"
}
}
}See the tests for a complete example project that excercises all the features of this library.
Run tests:
$> make test