Skip to content

Commit a9d85cb

Browse files
committed
fixed rendering of non paginated responses
1 parent cf8a930 commit a9d85cb

10 files changed

+151
-29
lines changed

‎example/settings/dev.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,12 @@
3939
JSON_API_FORMAT_KEYS = 'camelize'
4040
JSON_API_FORMAT_RELATION_KEYS = 'camelize'
4141
REST_FRAMEWORK = {
42-
'PAGINATE_BY': 5,
43-
'PAGINATE_BY_PARAM': 'page_size',
44-
'MAX_PAGINATE_BY': 100,
42+
# 'PAGINATE_BY': 5,
43+
# 'PAGINATE_BY_PARAM': 'page_size',
44+
# 'MAX_PAGINATE_BY': 100,
45+
'PAGE_SIZE': 5,
46+
# 'PAGINATE_BY_PARAM' should now be in the pagination class
47+
# Same for 'MAX_PAGINATE_BY'.
4548
'EXCEPTION_HANDLER': 'rest_framework_json_api.exceptions.exception_handler',
4649
'DEFAULT_PAGINATION_CLASS':
4750
'rest_framework_json_api.pagination.PageNumberPagination',

‎example/settings/test.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,6 @@
1313
JSON_API_FORMAT_RELATION_KEYS = 'camelize'
1414
JSON_API_PLURALIZE_RELATION_TYPE = True
1515
REST_FRAMEWORK.update({
16-
'PAGINATE_BY': 1,
16+
# 'PAGINATE_BY': 1,
17+
'PAGE_SIZE': 1,
1718
})

‎example/tests/conftest.py

+24
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,27 @@
66
register(BlogFactory)
77
register(AuthorFactory)
88
register(EntryFactory)
9+
10+
11+
@pytest.fixture
12+
def single_entry(author_factory, entry_factory):
13+
14+
author = author_factory(name="Joel Spolsky")
15+
entry = entry_factory(
16+
headline=("The Absolute Minimum Every Software Developer"
17+
"Absolutely, Positively Must Know About Unicode "
18+
"and Character Sets (No Excuses!)"),
19+
blog__name='Joel on Software',
20+
authors=(author, )
21+
)
22+
23+
24+
@pytest.fixture
25+
def multiple_entries(single_entry, author_factory, entry_factory):
26+
27+
author = author_factory(name="Ned Batchelder")
28+
entry = entry_factory(
29+
headline=("Pragmatic Unicode"),
30+
blog__name='Ned Batchelder Blog',
31+
authors=(author, )
32+
)

‎example/tests/test_format_keys.py

+7-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,17 @@ def setUp(self):
1818
self.detail_url = reverse('user-detail', kwargs={'pk': self.miles.pk})
1919

2020
# Set the format keys settings.
21-
setattr(settings, 'JSON_API_FORMAT_KEYS', 'camelize')
21+
# The below line is redundant because the default settings already
22+
# use 'camelize'
23+
# setattr(settings, 'JSON_API_FORMAT_KEYS', 'camelize')
2224
# CAMELIZE capitalize the type, needs to be checked
2325

2426
def tearDown(self):
27+
pass
2528
# Remove the format keys settings.
26-
setattr(settings, 'JSON_API_FORMAT_KEYS', 'dasherize')
29+
# The below line is redundant because the default settings already
30+
# use 'camelize'
31+
# setattr(settings, 'JSON_API_FORMAT_KEYS', 'camelize')
2732

2833

2934
def test_camelization(self):

‎example/tests/test_generic_viewset.py

+10
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ class GenericViewSet(TestBase):
1111
"""
1212
Test expected responses coming from a Generic ViewSet
1313
"""
14+
15+
def setUp(self):
16+
super(GenericViewSet, self).setUp()
17+
18+
setattr(settings, 'JSON_API_FORMAT_KEYS', 'dasherize')
19+
20+
def tearDown(self):
21+
22+
setattr(settings, 'JSON_API_FORMAT_KEYS', 'camelize')
23+
1424
def test_default_rest_framework_behavior(self):
1525
"""
1626
This is more of an example really, showing default behavior

‎example/tests/test_model_viewsets.py

+7
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from django.contrib.auth import get_user_model
44
from django.utils import encoding
55
from django.core.urlresolvers import reverse
6+
from django.conf import settings
67

78
from example.tests import TestBase
89
from example.tests.utils import dump_json, redump_json
@@ -22,6 +23,12 @@ def setUp(self):
2223
super(ModelViewSetTests, self).setUp()
2324
self.detail_url = reverse('user-detail', kwargs={'pk': self.miles.pk})
2425

26+
setattr(settings, 'JSON_API_FORMAT_KEYS', 'dasherize')
27+
28+
def tearDown(self):
29+
30+
setattr(settings, 'JSON_API_FORMAT_KEYS', 'camelize')
31+
2532
def test_key_in_list_result(self):
2633
"""
2734
Ensure the result has a 'user' key since that is the name of the model
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
from django.core.urlresolvers import reverse
2+
from django.conf import settings
3+
4+
import pytest
5+
6+
from ..views import EntryViewSet
7+
from rest_framework_json_api.pagination import PageNumberPagination
8+
9+
from example.tests.utils import dump_json, redump_json
10+
11+
pytestmark = pytest.mark.django_db
12+
13+
14+
def test_multiple_entries_no_pagination(rf, multiple_entries):
15+
16+
expected = {
17+
"data": [
18+
{
19+
"type": "posts",
20+
"id": "1",
21+
"attributes":
22+
{
23+
"headline": "The Absolute Minimum Every Software DeveloperAbsolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)",
24+
"bodyText": "Here goes the body text",
25+
"pubDate": None,
26+
"modDate": None
27+
},
28+
"relationships":
29+
{
30+
"blog": {
31+
"data": {"type": "blogs", "id": "1"}
32+
},
33+
"authors": {
34+
"meta": {"count": 1},
35+
"data": [{"type": "authors", "id": "1"}]
36+
}
37+
}
38+
},
39+
{
40+
"type": "posts",
41+
"id": "2",
42+
"attributes":
43+
{
44+
"headline": "Pragmatic Unicode",
45+
"bodyText": "Here goes the body text",
46+
"pubDate": None,
47+
"modDate": None
48+
},
49+
"relationships":
50+
{
51+
"blog": {
52+
"data": {"type": "blogs", "id": "2"}
53+
},
54+
"authors": {
55+
"meta": {"count": 1},
56+
"data": [{"type": "authors", "id": "2"}]
57+
}
58+
}
59+
},
60+
]
61+
}
62+
63+
class NoPagination(PageNumberPagination):
64+
page_size = None
65+
66+
class NonPaginatedEntryViewSet(EntryViewSet):
67+
pagination_class = NoPagination
68+
69+
request = rf.get(
70+
reverse("entry-list"))
71+
view = NonPaginatedEntryViewSet.as_view({'get': 'list'})
72+
response = view(request)
73+
response.render()
74+
# print response.content
75+
content_dump = redump_json(response.content)
76+
expected_dump = dump_json(expected)
77+
78+
assert content_dump == expected_dump

‎example/tests/test_pagination.py

+3-16
Original file line numberDiff line numberDiff line change
@@ -6,19 +6,6 @@
66
pytestmark = pytest.mark.django_db
77

88

9-
@pytest.fixture
10-
def single_entry(author_factory, entry_factory):
11-
12-
author = author_factory(name="Joel Spolsky")
13-
entry = entry_factory(
14-
headline=("The Absolute Minimum Every Software Developer"
15-
"Absolutely, Positively Must Know About Unicode "
16-
"and Character Sets (No Excuses!)"),
17-
blog__name='Joel on Software',
18-
authors=(author, )
19-
)
20-
21-
229
def test_pagination_with_single_entry(single_entry, client):
2310

2411
expected = {
@@ -29,9 +16,9 @@ def test_pagination_with_single_entry(single_entry, client):
2916
"attributes":
3017
{
3118
"headline": "The Absolute Minimum Every Software DeveloperAbsolutely, Positively Must Know About Unicode and Character Sets (No Excuses!)",
32-
"body-text": "Here goes the body text",
33-
"pub-date": None,
34-
"mod-date": None
19+
"bodyText": "Here goes the body text",
20+
"pubDate": None,
21+
"modDate": None
3522
},
3623
"relationships":
3724
{

‎rest_framework_json_api/pagination.py

+3
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,9 @@ class PageNumberPagination(BasePagination):
109109
A json-api compatible pagination format
110110
"""
111111

112+
page_size_query_param = 'page_size'
113+
max_page_size = 100
114+
112115
def build_link(self, index):
113116
if not index:
114117
return None

‎rest_framework_json_api/renderers.py

+11-7
Original file line numberDiff line numberDiff line change
@@ -75,22 +75,26 @@ def render(self, data, accepted_media_type=None, renderer_context=None):
7575

7676
json_api_included = list()
7777

78-
if view and hasattr(view, 'action') and view.action == 'list' and \
79-
isinstance(data, dict) and 'results' in data:
78+
if view and hasattr(view, 'action') and view.action == 'list':
79+
# The below is not true for non-paginated responses
80+
# and isinstance(data, dict):
81+
8082
# If detail view then json api spec expects dict, otherwise a list
8183
# - http://jsonapi.org/format/#document-top-level
8284
# The `results` key may be missing if unpaginated or an OPTIONS request
85+
if 'results' in data:
86+
resources = data["results"]
87+
else:
88+
resources = data
8389

84-
results = data["results"]
85-
86-
resource_serializer = results.serializer
90+
resource_serializer = resources.serializer
8791

8892
# Get the serializer fields
8993
fields = utils.get_serializer_fields(resource_serializer)
9094

9195
json_api_data = list()
92-
for position in range(len(results)):
93-
resource = results[position] # Get current resource
96+
for position in range(len(resources)):
97+
resource = resources[position] # Get current resource
9498
resource_instance = resource_serializer.instance[position] # Get current instance
9599
json_api_data.append(
96100
utils.build_json_resource_obj(fields, resource, resource_instance, resource_name))

0 commit comments

Comments
 (0)