From c51ecb8a3b158750a3a1bc706b36ba7318d64d75 Mon Sep 17 00:00:00 2001 From: Stefan Heinemann Date: Tue, 9 Feb 2016 16:49:41 +0100 Subject: [PATCH 1/3] Reverse the included relation name formatting --- rest_framework_json_api/renderers.py | 4 +++- rest_framework_json_api/serializers.py | 4 ++-- rest_framework_json_api/utils.py | 11 +++++++++++ 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/rest_framework_json_api/renderers.py b/rest_framework_json_api/renderers.py index a8e852cf..7018548b 100644 --- a/rest_framework_json_api/renderers.py +++ b/rest_framework_json_api/renderers.py @@ -406,10 +406,12 @@ def render(self, data, accepted_media_type=None, renderer_context=None): include_resources_param = request.query_params.get('include') if request else None if include_resources_param: - included_resources = include_resources_param.split(',') + included_resources = [".".join([utils.parse_relation_name(part) for part in resource.split('.')]) + for resource in include_resources_param.split(',')] else: included_resources = list() + json_api_included = list() # initialize json_api_meta with pagination meta or an empty dict json_api_meta = data.get('meta', {}) if isinstance(data, dict) else {} diff --git a/rest_framework_json_api/serializers.py b/rest_framework_json_api/serializers.py index f68d984e..b980a970 100644 --- a/rest_framework_json_api/serializers.py +++ b/rest_framework_json_api/serializers.py @@ -5,7 +5,7 @@ from rest_framework_json_api.relations import ResourceRelatedField from rest_framework_json_api.utils import ( get_resource_type_from_model, get_resource_type_from_instance, - get_resource_type_from_serializer, get_included_serializers) + get_resource_type_from_serializer, get_included_serializers, parse_relation_name) class ResourceIdentifierObjectSerializer(BaseSerializer): @@ -75,7 +75,7 @@ def validate_path(serializer_class, field_path, path): serializers = get_included_serializers(serializer_class) if serializers is None: raise ParseError('This endpoint does not support the include parameter') - this_field_name = field_path[0] + this_field_name = parse_relation_name(field_path[0]) this_included_serializer = serializers.get(this_field_name) if this_included_serializer is None: raise ParseError( diff --git a/rest_framework_json_api/utils.py b/rest_framework_json_api/utils.py index d8a4e67a..5b9a02b5 100644 --- a/rest_framework_json_api/utils.py +++ b/rest_framework_json_api/utils.py @@ -148,6 +148,17 @@ def format_relation_name(value, format_type=None): return inflection.pluralize(value) if pluralize else value +def parse_relation_name(value, format_type=None): + if format_type is None: + format_type = getattr(settings, 'JSON_API_PARSE_RELATION_KEYS', False) + + singularize = getattr(settings, 'JSON_API_SINGULARIZE_INCLUDE_TYPE', False) + + if format_type: + value = format_value(value, format_type) + + return inflection.singularize(value) if singularize else value + def get_related_resource_type(relation): if hasattr(relation, '_meta'): From 09a0a111e90a8b6ab05e028aa8737dc6a6f8fac0 Mon Sep 17 00:00:00 2001 From: Stefan Heinemann Date: Tue, 16 Feb 2016 15:01:12 +0100 Subject: [PATCH 2/3] Added test for the included names parsing --- example/serializers.py | 2 ++ example/tests/integration/test_includes.py | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/example/serializers.py b/example/serializers.py index c16b7cdf..19e69561 100644 --- a/example/serializers.py +++ b/example/serializers.py @@ -34,8 +34,10 @@ def __init__(self, *args, **kwargs): included_serializers = { 'comments': 'example.serializers.CommentSerializer', 'suggested': 'example.serializers.EntrySerializer', + 'blog': 'example.serializers.BlogSerializer' } + blog = serializers.ResourceRelatedField(read_only=True) body_format = serializers.SerializerMethodField() comments = relations.ResourceRelatedField( source='comment_set', many=True, read_only=True) diff --git a/example/tests/integration/test_includes.py b/example/tests/integration/test_includes.py index 4e8c79ce..f3e60939 100644 --- a/example/tests/integration/test_includes.py +++ b/example/tests/integration/test_includes.py @@ -50,3 +50,21 @@ def test_missing_field_not_included(author_bio_factory, author_factory, client): assert 'included' in data assert len(data['included']) == 1 assert data['included'][0]['attributes']['body'] == bio.body + +def test_reverse_included(single_entry, client): + """Test the parsing of included names""" + from django.conf import settings + + parse_relation = getattr(settings, 'JSON_API_PARSE_RELATION_KEYS', None) + singularize_included = getattr(settings, 'JSON_API_SINGULARIZE_INCLUDE_TYPE', None) + + settings.JSON_API_PARSE_RELATION_KEYS = 'underscore' + settings.JSON_API_SINGULARIZE_INCLUDE_TYPE = True + + response = client.get(reverse('entry-list') + '?include=blogs') + included = load_json(response.content).get('included') + + assert [x.get('type') for x in included] == ['blogs'], 'Related Blogs are incorrect' + + settings.JSON_API_PARSE_RELATION_KEYS = parse_relation + settings.JSON_API_SINGULARIZE_INCLUDE_TYPE = singularize_included From 7cd98c527bb81198aec574f5728a219482b32009 Mon Sep 17 00:00:00 2001 From: Stefan Heinemann Date: Tue, 16 Feb 2016 15:02:59 +0100 Subject: [PATCH 3/3] Better name for the parse include keys option --- example/tests/integration/test_includes.py | 6 +++--- rest_framework_json_api/utils.py | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/example/tests/integration/test_includes.py b/example/tests/integration/test_includes.py index f3e60939..b16b2949 100644 --- a/example/tests/integration/test_includes.py +++ b/example/tests/integration/test_includes.py @@ -55,10 +55,10 @@ def test_reverse_included(single_entry, client): """Test the parsing of included names""" from django.conf import settings - parse_relation = getattr(settings, 'JSON_API_PARSE_RELATION_KEYS', None) + parse_relation = getattr(settings, 'JSON_API_PARSE_INCLUDE_KEYS', None) singularize_included = getattr(settings, 'JSON_API_SINGULARIZE_INCLUDE_TYPE', None) - settings.JSON_API_PARSE_RELATION_KEYS = 'underscore' + settings.JSON_API_PARSE_INCLUDE_KEYS = 'underscore' settings.JSON_API_SINGULARIZE_INCLUDE_TYPE = True response = client.get(reverse('entry-list') + '?include=blogs') @@ -66,5 +66,5 @@ def test_reverse_included(single_entry, client): assert [x.get('type') for x in included] == ['blogs'], 'Related Blogs are incorrect' - settings.JSON_API_PARSE_RELATION_KEYS = parse_relation + settings.JSON_API_PARSE_INCLUDE_KEYS = parse_relation settings.JSON_API_SINGULARIZE_INCLUDE_TYPE = singularize_included diff --git a/rest_framework_json_api/utils.py b/rest_framework_json_api/utils.py index 5b9a02b5..e0369f5e 100644 --- a/rest_framework_json_api/utils.py +++ b/rest_framework_json_api/utils.py @@ -150,7 +150,7 @@ def format_relation_name(value, format_type=None): def parse_relation_name(value, format_type=None): if format_type is None: - format_type = getattr(settings, 'JSON_API_PARSE_RELATION_KEYS', False) + format_type = getattr(settings, 'JSON_API_PARSE_INCLUDE_KEYS', False) singularize = getattr(settings, 'JSON_API_SINGULARIZE_INCLUDE_TYPE', False)