Skip to content
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
Adam Wróbel <https://adamwrobel.com>
Adam Ziolkowski <adam@adsized.com>
Alan Crosswell <alan@columbia.edu>
Anton Shutik <shutikanton@gmail.com>
Christian Zosel <https://zosel.ch>
Greg Aker <greg@gregaker.net>
Jamie Bliss <astronouth7303@gmail.com>
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

* Add testing configuration to `REST_FRAMEWORK` configuration as described in [DRF](http://www.django-rest-framework.org/api-guide/testing/#configuration)
* Add sorting configuration to `REST_FRAMEWORK` as defined in [json api spec](http://jsonapi.org/format/#fetching-sorting)
* Add `HyperlinkedRelatedField` and `SerializerMethodHyperlinkedRelatedField`. See [usage docs](docs/usage.md#related-fields)


v2.5.0 - Released July 11, 2018
Expand Down
8 changes: 8 additions & 0 deletions docs/usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,6 +324,8 @@ When set to pluralize:

### Related fields

#### ResourceRelatedField

Because of the additional structure needed to represent relationships in JSON
API, this package provides the `ResourceRelatedField` for serializers, which
works similarly to `PrimaryKeyRelatedField`. By default,
Expand Down Expand Up @@ -435,6 +437,12 @@ class LineItemViewSet(viewsets.ModelViewSet):
return queryset
```

#### HyperlinkedRelatedField

`HyperlinkedRelatedField` has same functionality as `ResourceRelatedField` but does
not render `data`. Use this in case you only need links of relationships and want to lower payload
and increase performance.

### RelationshipView
`rest_framework_json_api.views.RelationshipView` is used to build
relationship views (see the
Expand Down
46 changes: 43 additions & 3 deletions example/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,19 +67,58 @@ def __init__(self, *args, **kwargs):
}

body_format = serializers.SerializerMethodField()
# single related from model
blog_hyperlinked = relations.HyperlinkedRelatedField(
related_link_view_name='entry-blog',
related_link_url_kwarg='entry_pk',
self_link_view_name='entry-relationships',
read_only=True,
source='blog'
)
# many related from model
comments = relations.ResourceRelatedField(
many=True, read_only=True)
# many related hyperlinked from model
comments_hyperlinked = relations.HyperlinkedRelatedField(
related_link_view_name='entry-comments',
related_link_url_kwarg='entry_pk',
self_link_view_name='entry-relationships',
many=True,
read_only=True,
source='comments'
)
# many related from serializer
suggested = relations.SerializerMethodResourceRelatedField(
source='get_suggested', model=Entry, many=True, read_only=True,
related_link_view_name='entry-suggested',
related_link_url_kwarg='entry_pk',
self_link_view_name='entry-relationships',
source='get_suggested',
model=Entry,
many=True,
read_only=True
)
# many related hyperlinked from serializer
suggested_hyperlinked = relations.SerializerMethodHyperlinkedRelatedField(
related_link_view_name='entry-suggested',
related_link_url_kwarg='entry_pk',
self_link_view_name='entry-relationships',
source='get_suggested',
model=Entry,
many=True,
read_only=True
)
# single related from serializer
featured = relations.SerializerMethodResourceRelatedField(
source='get_featured', model=Entry, read_only=True)
# single related hyperlinked from serializer
featured_hyperlinked = relations.SerializerMethodHyperlinkedRelatedField(
related_link_view_name='entry-featured',
related_link_url_kwarg='entry_pk',
self_link_view_name='entry-relationships',
source='get_featured',
model=Entry,
read_only=True
)
tags = TaggedItemSerializer(many=True, read_only=True)

def get_suggested(self, obj):
Expand All @@ -93,8 +132,9 @@ def get_body_format(self, obj):

class Meta:
model = Entry
fields = ('blog', 'headline', 'body_text', 'pub_date', 'mod_date',
'authors', 'comments', 'featured', 'suggested', 'tags')
fields = ('blog', 'blog_hyperlinked', 'headline', 'body_text', 'pub_date', 'mod_date',
'authors', 'comments', 'comments_hyperlinked', 'featured', 'suggested',
'suggested_hyperlinked', 'tags', 'featured_hyperlinked')
read_only_fields = ('tags',)
meta_fields = ('body_format',)

Expand Down
50 changes: 50 additions & 0 deletions example/tests/integration/test_non_paginated_responses.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,12 @@ def test_multiple_entries_no_pagination(multiple_entries, client):
"blog": {
"data": {"type": "blogs", "id": "1"}
},
"blogHyperlinked": {
"links": {
"related": "http://testserver/entries/1/blog",
"self": "http://testserver/entries/1/relationships/blog_hyperlinked"
}
},
"authors": {
"meta": {"count": 1},
"data": [{"type": "authors", "id": "1"}]
Expand All @@ -43,13 +49,32 @@ def test_multiple_entries_no_pagination(multiple_entries, client):
"meta": {"count": 1},
"data": [{"type": "comments", "id": "1"}]
},
"commentsHyperlinked": {
"links": {
"related": "http://testserver/entries/1/comments",
"self": "http://testserver/entries/1/relationships/comments_hyperlinked"
}
},
"suggested": {
"data": [{"type": "entries", "id": "2"}],
"links": {
"related": "http://testserver/entries/1/suggested/",
"self": "http://testserver/entries/1/relationships/suggested"
}
},
"suggestedHyperlinked": {
"links": {
"related": "http://testserver/entries/1/suggested/",
"self": "http://testserver/entries/1"
"/relationships/suggested_hyperlinked"
}
},
"featuredHyperlinked": {
"links": {
"related": "http://testserver/entries/1/featured",
"self": "http://testserver/entries/1/relationships/featured_hyperlinked"
}
},
"tags": {
"data": []
}
Expand All @@ -73,6 +98,12 @@ def test_multiple_entries_no_pagination(multiple_entries, client):
"blog": {
"data": {"type": "blogs", "id": "2"}
},
"blogHyperlinked": {
"links": {
"related": "http://testserver/entries/2/blog",
"self": "http://testserver/entries/2/relationships/blog_hyperlinked",
}
},
"authors": {
"meta": {"count": 1},
"data": [{"type": "authors", "id": "2"}]
Expand All @@ -81,13 +112,32 @@ def test_multiple_entries_no_pagination(multiple_entries, client):
"meta": {"count": 1},
"data": [{"type": "comments", "id": "2"}]
},
"commentsHyperlinked": {
"links": {
"related": "http://testserver/entries/2/comments",
"self": "http://testserver/entries/2/relationships/comments_hyperlinked"
}
},
"suggested": {
"data": [{"type": "entries", "id": "1"}],
"links": {
"related": "http://testserver/entries/2/suggested/",
"self": "http://testserver/entries/2/relationships/suggested"
}
},
"suggestedHyperlinked": {
"links": {
"related": "http://testserver/entries/2/suggested/",
"self": "http://testserver/entries/2"
"/relationships/suggested_hyperlinked"
}
},
"featuredHyperlinked": {
"links": {
"related": "http://testserver/entries/2/featured",
"self": "http://testserver/entries/2/relationships/featured_hyperlinked"
}
},
"tags": {
"data": []
}
Expand Down
25 changes: 25 additions & 0 deletions example/tests/integration/test_pagination.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ def test_pagination_with_single_entry(single_entry, client):
"blog": {
"data": {"type": "blogs", "id": "1"}
},
"blogHyperlinked": {
"links": {
"related": "http://testserver/entries/1/blog",
"self": "http://testserver/entries/1/relationships/blog_hyperlinked",
}
},
"authors": {
"meta": {"count": 1},
"data": [{"type": "authors", "id": "1"}]
Expand All @@ -44,13 +50,32 @@ def test_pagination_with_single_entry(single_entry, client):
"meta": {"count": 1},
"data": [{"type": "comments", "id": "1"}]
},
"commentsHyperlinked": {
"links": {
"related": "http://testserver/entries/1/comments",
"self": "http://testserver/entries/1/relationships/comments_hyperlinked"
}
},
"suggested": {
"data": [],
"links": {
"related": "http://testserver/entries/1/suggested/",
"self": "http://testserver/entries/1/relationships/suggested"
}
},
"suggestedHyperlinked": {
"links": {
"related": "http://testserver/entries/1/suggested/",
"self": "http://testserver/entries/1"
"/relationships/suggested_hyperlinked"
}
},
"featuredHyperlinked": {
"links": {
"related": "http://testserver/entries/1/featured",
"self": "http://testserver/entries/1/relationships/featured_hyperlinked"
}
},
"tags": {
"data": [
{
Expand Down
Loading