Repository: django-json-api/django-rest-framework-json-api

Issue:
inflector configuration
Hi,
I found a problem with configuration,

```
JSON_API_FORMAT_KEYS = 'underscore'
```

has no effect:

```
{
"data": {
    "type": "List",
    "id": "fb2c1e3c-0255-4c4c-82c5-2eb3e3e62529",
    "attributes": {
        "title": "super seznam"
    },
    "relationships": {
        "owner": {
            "data": {
                "type": "User",
                "id": "de394d10-c664-4fbe-9668-0df803e2cfa1"
            }
        },
        "category": {
            "data": {
                "type": "ListCategory",
                "id": "1"
            }
        }
    },
    "links": {
        "self": "http://127.0.0.1:8000/api/lists/fb2c1e3c-0255-4c4c-82c5-2eb3e3e62529/"
    }
}
}

JSON_API_FORMAT_RELATION_KEYS = 'underscore'
```

affects all "type" names:

```
{
"data": {
    "type": "list",
    "id": "fb2c1e3c-0255-4c4c-82c5-2eb3e3e62529",
    "attributes": {
        "title": "super seznam"
    },
    "relationships": {
        "owner": {
            "data": {
                "type": "user",
                "id": "de394d10-c664-4fbe-9668-0df803e2cfa1"
            }
        },
        "category": {
            "data": {
                "type": "list_category",
                "id": "1"
            }
        }
    },
    "links": {
        "self": "http://127.0.0.1:8000/api/lists/fb2c1e3c-0255-4c4c-82c5-2eb3e3e62529/"
    }
}
}
```



Discussion:
`JSON_API_FORMAT_KEYS` is for attributes/relationship names not their types - what is your expected behavior ?

So `JSON_API_FORMAT_KEYS`  is for attributes/relationship names and `JSON_API_FORMAT_RELATION_KEYS` for types, Why isn't it called `JSON_API_FORMAT_RELATION_TYPE` like `JSON_API_PLURALIZE_RELATION_TYPE`? Or just only `JSON_API_FORMAT_TYPE` ?


Resolving patch:
diff --git a/example/settings/dev.py b/example/settings/dev.py
--- a/example/settings/dev.py
+++ b/example/settings/dev.py
@@ -37,7 +37,7 @@
 MIDDLEWARE_CLASSES = ()
 
 JSON_API_FORMAT_KEYS = 'camelize'
-JSON_API_FORMAT_RELATION_KEYS = 'camelize'
+JSON_API_FORMAT_TYPES = 'camelize'
 REST_FRAMEWORK = {
     'PAGE_SIZE': 5,
     'EXCEPTION_HANDLER': 'rest_framework_json_api.exceptions.exception_handler',
diff --git a/rest_framework_json_api/renderers.py b/rest_framework_json_api/renderers.py
--- a/rest_framework_json_api/renderers.py
+++ b/rest_framework_json_api/renderers.py
@@ -208,7 +208,7 @@ def extract_relationships(fields, resource, resource_instance):
 
             if isinstance(field, ModelSerializer):
                 relation_model = field.Meta.model
-                relation_type = utils.format_relation_name(relation_model.__name__)
+                relation_type = utils.format_type(relation_model.__name__)
 
                 data.update({
                     field_name: {
@@ -343,7 +343,7 @@ def extract_root_meta(serializer, resource):
         if hasattr(serializer, 'child'):
             many = True
             serializer = serializer.child
-        
+
         data = {}
         if getattr(serializer, 'get_root_meta', None):
             json_api_meta = serializer.get_root_meta(resource, many)
diff --git a/rest_framework_json_api/utils.py b/rest_framework_json_api/utils.py
--- a/rest_framework_json_api/utils.py
+++ b/rest_framework_json_api/utils.py
@@ -2,6 +2,7 @@
 Utils.
 """
 import copy
+import warnings
 from collections import OrderedDict
 
 import inflection
@@ -59,7 +60,7 @@ def get_resource_name(context):
                 return resource_name
 
             # the name was calculated automatically from the view > pluralize and format
-            resource_name = format_relation_name(resource_name)
+            resource_name = format_resource_type(resource_name)
 
     return resource_name
 
@@ -137,10 +138,18 @@ def format_value(value, format_type=None):
 
 
 def format_relation_name(value, format_type=None):
+    warnings.warn("The 'format_relation_name' function has been renamed 'format_resource_type' and the settings are now 'JSON_API_FORMAT_TYPES' and 'JSON_API_PLURALIZE_TYPES'")
     if format_type is None:
-        format_type = getattr(settings, 'JSON_API_FORMAT_RELATION_KEYS', False)
+        format_type = getattr(settings, 'JSON_API_FORMAT_RELATION_KEYS', None)
+    pluralize = getattr(settings, 'JSON_API_PLURALIZE_RELATION_TYPE', None)
+    return format_resource_type(value, format_type, pluralize)
 
-    pluralize = getattr(settings, 'JSON_API_PLURALIZE_RELATION_TYPE', False)
+def format_resource_type(value, format_type=None, pluralize=None):
+    if format_type is None:
+        format_type = getattr(settings, 'JSON_API_FORMAT_TYPES', False)
+
+    if pluralize is None:
+        pluralize = getattr(settings, 'JSON_API_PLURALIZE_TYPES', False)
 
     if format_type:
         # format_type will never be None here so we can use format_value
@@ -198,7 +207,7 @@ def get_resource_type_from_model(model):
     return getattr(
         json_api_meta,
         'resource_name',
-        format_relation_name(model.__name__))
+        format_resource_type(model.__name__))
 
 
 def get_resource_type_from_queryset(qs):


Test patch:
diff --git a/example/settings/test.py b/example/settings/test.py
--- a/example/settings/test.py
+++ b/example/settings/test.py
@@ -10,8 +10,8 @@
 ROOT_URLCONF = 'example.urls_test'
 
 JSON_API_FORMAT_KEYS = 'camelize'
-JSON_API_FORMAT_RELATION_KEYS = 'camelize'
-JSON_API_PLURALIZE_RELATION_TYPE = True
+JSON_API_FORMAT_TYPES = 'camelize'
+JSON_API_PLURALIZE_TYPES = True
 REST_FRAMEWORK.update({
     'PAGE_SIZE': 1,
 })
diff --git a/example/tests/test_relations.py b/example/tests/test_relations.py
--- a/example/tests/test_relations.py
+++ b/example/tests/test_relations.py
@@ -5,7 +5,7 @@
 
 from . import TestBase
 from rest_framework_json_api.exceptions import Conflict
-from rest_framework_json_api.utils import format_relation_name
+from rest_framework_json_api.utils import format_resource_type
 from example.models import Blog, Entry, Comment, Author
 from example.serializers import CommentSerializer
 from rest_framework_json_api.relations import ResourceRelatedField
@@ -42,7 +42,7 @@ def test_data_in_correct_format_when_instantiated_with_blog_object(self):
         serializer = BlogFKSerializer(instance={'blog': self.blog})
 
         expected_data = {
-            'type': format_relation_name('Blog'),
+            'type': format_resource_type('Blog'),
             'id': str(self.blog.id)
         }
 
@@ -54,7 +54,7 @@ def test_data_in_correct_format_when_instantiated_with_entry_object(self):
         serializer = EntryFKSerializer(instance={'entry': self.entry})
 
         expected_data = {
-            'type': format_relation_name('Entry'),
+            'type': format_resource_type('Entry'),
             'id': str(self.entry.id)
         }
 
@@ -65,7 +65,7 @@ def test_data_in_correct_format_when_instantiated_with_entry_object(self):
     def test_deserialize_primitive_data_blog(self):
         serializer = BlogFKSerializer(data={
             'blog': {
-                'type': format_relation_name('Blog'),
+                'type': format_resource_type('Blog'),
                 'id': str(self.blog.id)
             }
         }
@@ -90,7 +90,7 @@ def test_validation_fails_for_wrong_type(self):
     def test_serialize_many_to_many_relation(self):
         serializer = EntryModelSerializer(instance=self.entry)
 
-        type_string = format_relation_name('Author')
+        type_string = format_resource_type('Author')
         author_pks = Author.objects.values_list('pk', flat=True)
         expected_data = [{'type': type_string, 'id': str(pk)} for pk in author_pks]
 
@@ -100,7 +100,7 @@ def test_serialize_many_to_many_relation(self):
         )
 
     def test_deserialize_many_to_many_relation(self):
-        type_string = format_relation_name('Author')
+        type_string = format_resource_type('Author')
         author_pks = Author.objects.values_list('pk', flat=True)
         authors = [{'type': type_string, 'id': pk} for pk in author_pks]
 
diff --git a/example/tests/test_serializers.py b/example/tests/test_serializers.py
--- a/example/tests/test_serializers.py
+++ b/example/tests/test_serializers.py
@@ -2,7 +2,7 @@
 from django.test import TestCase
 from django.utils import timezone
 
-from rest_framework_json_api.utils import format_relation_name
+from rest_framework_json_api.utils import format_resource_type
 from rest_framework_json_api.serializers import ResourceIdentifierObjectSerializer
 
 from example.models import Blog, Entry, Author
@@ -35,20 +35,20 @@ def setUp(self):
     def test_data_in_correct_format_when_instantiated_with_blog_object(self):
         serializer = ResourceIdentifierObjectSerializer(instance=self.blog)
 
-        expected_data = {'type': format_relation_name('Blog'), 'id': str(self.blog.id)}
+        expected_data = {'type': format_resource_type('Blog'), 'id': str(self.blog.id)}
 
         assert serializer.data == expected_data
 
     def test_data_in_correct_format_when_instantiated_with_entry_object(self):
         serializer = ResourceIdentifierObjectSerializer(instance=self.entry)
 
-        expected_data = {'type': format_relation_name('Entry'), 'id': str(self.entry.id)}
+        expected_data = {'type': format_resource_type('Entry'), 'id': str(self.entry.id)}
 
         assert serializer.data == expected_data
 
     def test_deserialize_primitive_data_blog(self):
         initial_data = {
-            'type': format_relation_name('Blog'),
+            'type': format_resource_type('Blog'),
             'id': str(self.blog.id)
         }
         serializer = ResourceIdentifierObjectSerializer(data=initial_data, model_class=Blog)
@@ -60,14 +60,14 @@ def test_data_in_correct_format_when_instantiated_with_queryset(self):
         qs = Author.objects.all()
         serializer = ResourceIdentifierObjectSerializer(instance=qs, many=True)
 
-        type_string = format_relation_name('Author')
+        type_string = format_resource_type('Author')
         author_pks = Author.objects.values_list('pk', flat=True)
         expected_data = [{'type': type_string, 'id': str(pk)} for pk in author_pks]
 
         assert serializer.data == expected_data
 
     def test_deserialize_many(self):
-        type_string = format_relation_name('Author')
+        type_string = format_resource_type('Author')
         author_pks = Author.objects.values_list('pk', flat=True)
         initial_data = [{'type': type_string, 'id': str(pk)} for pk in author_pks]
 
diff --git a/example/tests/test_views.py b/example/tests/test_views.py
--- a/example/tests/test_views.py
+++ b/example/tests/test_views.py
@@ -5,7 +5,7 @@
 
 from rest_framework.test import APITestCase
 
-from rest_framework_json_api.utils import format_relation_name
+from rest_framework_json_api.utils import format_resource_type
 from example.models import Blog, Entry, Comment, Author
 
 
@@ -44,7 +44,7 @@ def setUp(self):
     def test_get_entry_relationship_blog(self):
         url = reverse('entry-relationships', kwargs={'pk': self.first_entry.id, 'related_field': 'blog'})
         response = self.client.get(url)
-        expected_data = {'type': format_relation_name('Blog'), 'id': str(self.first_entry.blog.id)}
+        expected_data = {'type': format_resource_type('Blog'), 'id': str(self.first_entry.blog.id)}
 
         assert response.data == expected_data
 
@@ -55,8 +55,8 @@ def test_get_entry_relationship_invalid_field(self):
 
     def test_get_blog_relationship_entry_set(self):
         response = self.client.get('/blogs/{}/relationships/entry_set'.format(self.blog.id))
-        expected_data = [{'type': format_relation_name('Entry'), 'id': str(self.first_entry.id)},
-                         {'type': format_relation_name('Entry'), 'id': str(self.second_entry.id)}]
+        expected_data = [{'type': format_resource_type('Entry'), 'id': str(self.first_entry.id)},
+                         {'type': format_resource_type('Entry'), 'id': str(self.second_entry.id)}]
 
         assert response.data == expected_data
 
@@ -85,14 +85,14 @@ def test_get_to_many_relationship_self_link(self):
         response = self.client.get(url)
         expected_data = {
             'links': {'self': 'http://testserver/authors/1/relationships/comment_set'},
-            'data': [{'id': str(self.second_comment.id), 'type': format_relation_name('Comment')}]
+            'data': [{'id': str(self.second_comment.id), 'type': format_resource_type('Comment')}]
         }
         assert json.loads(response.content.decode('utf-8')) == expected_data
 
     def test_patch_to_one_relationship(self):
         url = '/entries/{}/relationships/blog'.format(self.first_entry.id)
         request_data = {
-            'data': {'type': format_relation_name('Blog'), 'id': str(self.other_blog.id)}
+            'data': {'type': format_resource_type('Blog'), 'id': str(self.other_blog.id)}
         }
         response = self.client.patch(url, data=json.dumps(request_data), content_type='application/vnd.api+json')
         assert response.status_code == 200, response.content.decode()
@@ -103,7 +103,7 @@ def test_patch_to_one_relationship(self):
     def test_patch_to_many_relationship(self):
         url = '/blogs/{}/relationships/entry_set'.format(self.first_entry.id)
         request_data = {
-            'data': [{'type': format_relation_name('Entry'), 'id': str(self.first_entry.id)}, ]
+            'data': [{'type': format_resource_type('Entry'), 'id': str(self.first_entry.id)}, ]
         }
         response = self.client.patch(url, data=json.dumps(request_data), content_type='application/vnd.api+json')
         assert response.status_code == 200, response.content.decode()
@@ -114,7 +114,7 @@ def test_patch_to_many_relationship(self):
     def test_post_to_one_relationship_should_fail(self):
         url = '/entries/{}/relationships/blog'.format(self.first_entry.id)
         request_data = {
-            'data': {'type': format_relation_name('Blog'), 'id': str(self.other_blog.id)}
+            'data': {'type': format_resource_type('Blog'), 'id': str(self.other_blog.id)}
         }
         response = self.client.post(url, data=json.dumps(request_data), content_type='application/vnd.api+json')
         assert response.status_code == 405, response.content.decode()
@@ -122,7 +122,7 @@ def test_post_to_one_relationship_should_fail(self):
     def test_post_to_many_relationship_with_no_change(self):
         url = '/entries/{}/relationships/comment_set'.format(self.first_entry.id)
         request_data = {
-            'data': [{'type': format_relation_name('Comment'), 'id': str(self.first_comment.id)}, ]
+            'data': [{'type': format_resource_type('Comment'), 'id': str(self.first_comment.id)}, ]
         }
         response = self.client.post(url, data=json.dumps(request_data), content_type='application/vnd.api+json')
         assert response.status_code == 204, response.content.decode()
@@ -130,7 +130,7 @@ def test_post_to_many_relationship_with_no_change(self):
     def test_post_to_many_relationship_with_change(self):
         url = '/entries/{}/relationships/comment_set'.format(self.first_entry.id)
         request_data = {
-            'data': [{'type': format_relation_name('Comment'), 'id': str(self.second_comment.id)}, ]
+            'data': [{'type': format_resource_type('Comment'), 'id': str(self.second_comment.id)}, ]
         }
         response = self.client.post(url, data=json.dumps(request_data), content_type='application/vnd.api+json')
         assert response.status_code == 200, response.content.decode()
@@ -140,7 +140,7 @@ def test_post_to_many_relationship_with_change(self):
     def test_delete_to_one_relationship_should_fail(self):
         url = '/entries/{}/relationships/blog'.format(self.first_entry.id)
         request_data = {
-            'data': {'type': format_relation_name('Blog'), 'id': str(self.other_blog.id)}
+            'data': {'type': format_resource_type('Blog'), 'id': str(self.other_blog.id)}
         }
         response = self.client.delete(url, data=json.dumps(request_data), content_type='application/vnd.api+json')
         assert response.status_code == 405, response.content.decode()
@@ -164,7 +164,7 @@ def test_delete_relationship_overriding_with_none(self):
     def test_delete_to_many_relationship_with_no_change(self):
         url = '/entries/{}/relationships/comment_set'.format(self.first_entry.id)
         request_data = {
-            'data': [{'type': format_relation_name('Comment'), 'id': str(self.second_comment.id)}, ]
+            'data': [{'type': format_resource_type('Comment'), 'id': str(self.second_comment.id)}, ]
         }
         response = self.client.delete(url, data=json.dumps(request_data), content_type='application/vnd.api+json')
         assert response.status_code == 204, response.content.decode()
@@ -172,7 +172,7 @@ def test_delete_to_many_relationship_with_no_change(self):
     def test_delete_one_to_many_relationship_with_not_null_constraint(self):
         url = '/entries/{}/relationships/comment_set'.format(self.first_entry.id)
         request_data = {
-            'data': [{'type': format_relation_name('Comment'), 'id': str(self.first_comment.id)}, ]
+            'data': [{'type': format_resource_type('Comment'), 'id': str(self.first_comment.id)}, ]
         }
         response = self.client.delete(url, data=json.dumps(request_data), content_type='application/vnd.api+json')
         assert response.status_code == 409, response.content.decode()
@@ -180,7 +180,7 @@ def test_delete_one_to_many_relationship_with_not_null_constraint(self):
     def test_delete_to_many_relationship_with_change(self):
         url = '/authors/{}/relationships/comment_set'.format(self.author.id)
         request_data = {
-            'data': [{'type': format_relation_name('Comment'), 'id': str(self.second_comment.id)}, ]
+            'data': [{'type': format_resource_type('Comment'), 'id': str(self.second_comment.id)}, ]
         }
         response = self.client.delete(url, data=json.dumps(request_data), content_type='application/vnd.api+json')
         assert response.status_code == 200, response.content.decode()
diff --git a/example/tests/unit/test_utils.py b/example/tests/unit/test_utils.py
--- a/example/tests/unit/test_utils.py
+++ b/example/tests/unit/test_utils.py
@@ -29,11 +29,11 @@ class Meta:
 def test_get_resource_name():
     view = APIView()
     context = {'view': view}
-    setattr(settings, 'JSON_API_FORMAT_RELATION_KEYS', None)
+    setattr(settings, 'JSON_API_FORMAT_TYPES', None)
     assert 'APIViews' == utils.get_resource_name(context), 'not formatted'
 
     context = {'view': view}
-    setattr(settings, 'JSON_API_FORMAT_RELATION_KEYS', 'dasherize')
+    setattr(settings, 'JSON_API_FORMAT_TYPES', 'dasherize')
     assert 'api-views' == utils.get_resource_name(context), 'derived from view'
 
     view.model = get_user_model()
@@ -91,9 +91,9 @@ def test_format_value():
     assert utils.format_value('first-name', 'underscore') == 'first_name'
 
 
-def test_format_relation_name():
-    assert utils.format_relation_name('first_name', 'capitalize') == 'FirstNames'
-    assert utils.format_relation_name('first_name', 'camelize') == 'firstNames'
+def test_format_resource_type():
+    assert utils.format_resource_type('first_name', 'capitalize') == 'FirstNames'
+    assert utils.format_resource_type('first_name', 'camelize') == 'firstNames'
 
 
 class SerializerWithIncludedSerializers(EntrySerializer):