Skip to content

Commit 390d99c

Browse files
author
Boris Pleshakov
committed
Merge remote-tracking branch 'origin/patch-3' into patch-3
2 parents 7326681 + 82d2002 commit 390d99c

File tree

12 files changed

+194
-63
lines changed

12 files changed

+194
-63
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,4 @@ Nathanael Gordon <nathanael.l.gordon@gmail.com>
2828
Charlie Allatson <charles.allatson@gmail.com>
2929
Joseba Mendivil <git@jma.email>
3030
Felix Viernickel <felix@gedankenspieler.org>
31+
Tom Glowka <glowka.tom@gmail.com>

CHANGELOG.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,16 @@ any parts of the framework not mentioned in the documentation should generally b
1515
* Added support for serializiing complex structures as attributes. For details please reffer to #769
1616
* Avoid `AttributeError` for PUT and PATCH methods when using `APIView`
1717

18+
### Changed
19+
20+
* `SerializerMethodResourceRelatedField` is now consistent with DRF `SerializerMethodField`:
21+
* Pass `method_name` argument to specify method name. If no value is provided, it defaults to `get_{field_name}`
22+
23+
### Deprecated
24+
25+
* Deprecate `source` argument of `SerializerMethodResourceRelatedField`, use `method_name` instead
26+
27+
1828
## [3.1.0] - 2020-02-08
1929

2030
### Added

docs/usage.md

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -586,10 +586,68 @@ class LineItemViewSet(viewsets.ModelViewSet):
586586

587587
#### HyperlinkedRelatedField
588588

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

593+
#### SerializerMethodResourceRelatedField
594+
595+
`relations.SerializerMethodResourceRelatedField` combines behaviour of DRF `SerializerMethodField` and
596+
`ResourceRelatedField`, so it accepts `method_name` together with `model` and links-related arguments.
597+
`data` is rendered in `ResourceRelatedField` manner.
598+
599+
```python
600+
from rest_framework_json_api import serializers
601+
from rest_framework_json_api.relations import SerializerMethodResourceRelatedField
602+
603+
from myapp.models import Order, LineItem
604+
605+
606+
class OrderSerializer(serializers.ModelSerializer):
607+
class Meta:
608+
model = Order
609+
610+
line_items = SerializerMethodResourceRelatedField(
611+
model=LineItem,
612+
many=True,
613+
method_name='get_big_line_items'
614+
)
615+
616+
small_line_items = SerializerMethodResourceRelatedField(
617+
model=LineItem,
618+
many=True,
619+
# default to method_name='get_small_line_items'
620+
)
621+
622+
def get_big_line_items(self, instance):
623+
return LineItem.objects.filter(order=instance).filter(amount__gt=1000)
624+
625+
def get_small_line_items(self, instance):
626+
return LineItem.objects.filter(order=instance).filter(amount__lte=1000)
627+
628+
```
629+
630+
or using `related_link_*` with `HyperlinkedModelSerializer`
631+
632+
```python
633+
class OrderSerializer(serializers.HyperlinkedModelSerializer):
634+
class Meta:
635+
model = Order
636+
637+
line_items = SerializerMethodResourceRelatedField(
638+
model=LineItem,
639+
many=True,
640+
method_name='get_big_line_items',
641+
related_link_view_name='order-lineitems-list',
642+
related_link_url_kwarg='order_pk',
643+
)
644+
645+
def get_big_line_items(self, instance):
646+
return LineItem.objects.filter(order=instance).filter(amount__gt=1000)
647+
648+
```
649+
650+
593651
#### Related urls
594652

595653
There is a nice way to handle "related" urls like `/orders/3/lineitems/` or `/orders/3/customer/`.

example/serializers.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -126,30 +126,24 @@ def __init__(self, *args, **kwargs):
126126
related_link_view_name='entry-suggested',
127127
related_link_url_kwarg='entry_pk',
128128
self_link_view_name='entry-relationships',
129-
source='get_suggested',
130129
model=Entry,
131130
many=True,
132-
read_only=True
133131
)
134132
# many related hyperlinked from serializer
135133
suggested_hyperlinked = relations.SerializerMethodHyperlinkedRelatedField(
136134
related_link_view_name='entry-suggested',
137135
related_link_url_kwarg='entry_pk',
138136
self_link_view_name='entry-relationships',
139-
source='get_suggested',
140137
model=Entry,
141138
many=True,
142-
read_only=True
143139
)
144140
# single related from serializer
145-
featured = relations.SerializerMethodResourceRelatedField(
146-
source='get_featured', model=Entry, read_only=True)
141+
featured = relations.SerializerMethodResourceRelatedField(model=Entry)
147142
# single related hyperlinked from serializer
148143
featured_hyperlinked = relations.SerializerMethodHyperlinkedRelatedField(
149144
related_link_view_name='entry-featured',
150145
related_link_url_kwarg='entry_pk',
151146
self_link_view_name='entry-relationships',
152-
source='get_featured',
153147
model=Entry,
154148
read_only=True
155149
)
@@ -229,8 +223,6 @@ class AuthorSerializer(serializers.ModelSerializer):
229223
related_link_view_name='author-related',
230224
self_link_view_name='author-relationships',
231225
model=Entry,
232-
read_only=True,
233-
source='get_first_entry'
234226
)
235227
comments = relations.HyperlinkedRelatedField(
236228
related_link_view_name='author-related',

example/tests/test_parsers.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from django.conf.urls import url
55
from django.test import TestCase, override_settings
66
from django.urls import reverse
7-
from rest_framework import views, status
7+
from rest_framework import status, views
88
from rest_framework.exceptions import ParseError
99
from rest_framework.response import Response
1010
from rest_framework.test import APITestCase

example/tests/test_relations.py

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -290,16 +290,12 @@ class EntryModelSerializerWithHyperLinks(serializers.ModelSerializer):
290290
related_link_url_kwarg='entry_pk',
291291
self_link_view_name='entry-relationships',
292292
many=True,
293-
read_only=True,
294-
source='get_blog'
295293
)
296294
comments = SerializerMethodHyperlinkedRelatedField(
297295
related_link_view_name='entry-comments',
298296
related_link_url_kwarg='entry_pk',
299297
self_link_view_name='entry-relationships',
300298
many=True,
301-
read_only=True,
302-
source='get_comments'
303299
)
304300

305301
class Meta:

example/tests/test_serializers.py

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,21 +7,17 @@
77
from rest_framework.request import Request
88
from rest_framework.test import APIRequestFactory
99

10-
from example.factories import ArtProjectFactory
1110
from rest_framework_json_api.serializers import (
1211
DateField,
1312
ModelSerializer,
1413
ResourceIdentifierObjectSerializer,
15-
empty,
14+
empty
1615
)
1716
from rest_framework_json_api.utils import format_resource_type
1817

18+
from example.factories import ArtProjectFactory
1919
from example.models import Author, Blog, Entry
20-
from example.serializers import (
21-
BlogSerializer,
22-
ProjectSerializer,
23-
ArtProjectSerializer,
24-
)
20+
from example.serializers import ArtProjectSerializer, BlogSerializer, ProjectSerializer
2521

2622
request_factory = APIRequestFactory()
2723
pytestmark = pytest.mark.django_db
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
from __future__ import absolute_import
2+
3+
import pytest
4+
from rest_framework import serializers
5+
6+
from rest_framework_json_api.relations import SerializerMethodResourceRelatedField
7+
8+
from example.models import Blog, Entry
9+
10+
11+
def test_method_name_default():
12+
class BlogSerializer(serializers.ModelSerializer):
13+
one_entry = SerializerMethodResourceRelatedField(model=Entry)
14+
15+
class Meta:
16+
model = Blog
17+
fields = ['one_entry']
18+
19+
def get_one_entry(self, instance):
20+
return Entry(id=100)
21+
22+
serializer = BlogSerializer(instance=Blog())
23+
assert serializer.data['one_entry']['id'] == '100'
24+
25+
26+
def test_method_name_custom():
27+
class BlogSerializer(serializers.ModelSerializer):
28+
one_entry = SerializerMethodResourceRelatedField(
29+
model=Entry,
30+
method_name='get_custom_entry'
31+
)
32+
33+
class Meta:
34+
model = Blog
35+
fields = ['one_entry']
36+
37+
def get_custom_entry(self, instance):
38+
return Entry(id=100)
39+
40+
serializer = BlogSerializer(instance=Blog())
41+
assert serializer.data['one_entry']['id'] == '100'
42+
43+
44+
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
45+
def test_source():
46+
class BlogSerializer(serializers.ModelSerializer):
47+
one_entry = SerializerMethodResourceRelatedField(
48+
model=Entry,
49+
source='get_custom_entry'
50+
)
51+
52+
class Meta:
53+
model = Blog
54+
fields = ['one_entry']
55+
56+
def get_custom_entry(self, instance):
57+
return Entry(id=100)
58+
59+
serializer = BlogSerializer(instance=Blog())
60+
assert serializer.data['one_entry']['id'] == '100'
61+
62+
63+
@pytest.mark.filterwarnings("error::DeprecationWarning")
64+
def test_source_is_deprecated():
65+
with pytest.raises(DeprecationWarning):
66+
SerializerMethodResourceRelatedField(model=Entry, source='get_custom_entry')
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
flake8==3.7.9
2-
flake8-isort==2.8.0
2+
flake8-isort==3.0.0
33
isort==4.3.21
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
recommonmark==0.6.0
2-
Sphinx==2.4.4
2+
Sphinx==3.0.3
33
sphinx_rtd_theme==0.4.3

0 commit comments

Comments
 (0)