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

Issue:
Multi-words relation names error pointers are misformed
## Description of the Bug Report

#986 fixed #413 but did not covered multiple words in relations names.

Therefore, when fields names formatting is enforced, pointers still refers to `/attributes/` since inflection breaks field identification as a relationship.

A PR with the failing tests and the fix are on the way.

## Checklist

- [x] Certain that this is a bug (if unsure or you have a question use [discussions](https://github.com/django-json-api/django-rest-framework-json-api/discussions) instead)
- [x] Code snippet or unit test added to reproduce bug



Discussion:

Resolving patch:
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
@@ -380,7 +380,9 @@ def format_drf_errors(response, context, exc):
             serializer = context["view"].get_serializer()
             fields = get_serializer_fields(serializer) or dict()
             relationship_fields = [
-                name for name, field in fields.items() if is_relationship_field(field)
+                format_field_name(name)
+                for name, field in fields.items()
+                if is_relationship_field(field)
             ]
 
         for field, error in response.data.items():


Test patch:
diff --git a/example/tests/__snapshots__/test_errors.ambr b/example/tests/__snapshots__/test_errors.ambr
--- a/example/tests/__snapshots__/test_errors.ambr
+++ b/example/tests/__snapshots__/test_errors.ambr
@@ -47,14 +47,66 @@
     ]),
   })
 # ---
-# name: test_relationship_errors_has_correct_pointers
+# name: test_relationship_errors_has_correct_pointers_with_camelize
   dict({
     'errors': list([
       dict({
         'code': 'incorrect_type',
         'detail': 'Incorrect type. Expected resource identifier object, received str.',
         'source': dict({
-          'pointer': '/data/relationships/author',
+          'pointer': '/data/relationships/authors',
+        }),
+        'status': '400',
+      }),
+      dict({
+        'code': 'incorrect_type',
+        'detail': 'Incorrect type. Expected resource identifier object, received str.',
+        'source': dict({
+          'pointer': '/data/relationships/mainAuthor',
+        }),
+        'status': '400',
+      }),
+    ]),
+  })
+# ---
+# name: test_relationship_errors_has_correct_pointers_with_dasherize
+  dict({
+    'errors': list([
+      dict({
+        'code': 'incorrect_type',
+        'detail': 'Incorrect type. Expected resource identifier object, received str.',
+        'source': dict({
+          'pointer': '/data/relationships/authors',
+        }),
+        'status': '400',
+      }),
+      dict({
+        'code': 'incorrect_type',
+        'detail': 'Incorrect type. Expected resource identifier object, received str.',
+        'source': dict({
+          'pointer': '/data/relationships/main-author',
+        }),
+        'status': '400',
+      }),
+    ]),
+  })
+# ---
+# name: test_relationship_errors_has_correct_pointers_with_no_formatting
+  dict({
+    'errors': list([
+      dict({
+        'code': 'incorrect_type',
+        'detail': 'Incorrect type. Expected resource identifier object, received str.',
+        'source': dict({
+          'pointer': '/data/relationships/authors',
+        }),
+        'status': '400',
+      }),
+      dict({
+        'code': 'incorrect_type',
+        'detail': 'Incorrect type. Expected resource identifier object, received str.',
+        'source': dict({
+          'pointer': '/data/relationships/main_author',
         }),
         'status': '400',
       }),
diff --git a/example/tests/test_errors.py b/example/tests/test_errors.py
--- a/example/tests/test_errors.py
+++ b/example/tests/test_errors.py
@@ -30,9 +30,12 @@ class EntrySerializer(serializers.Serializer):
     comment = CommentSerializer(required=False)
     headline = serializers.CharField(allow_null=True, required=True)
     body_text = serializers.CharField()
-    author = serializers.ResourceRelatedField(
+    main_author = serializers.ResourceRelatedField(
         queryset=Author.objects.all(), required=False
     )
+    authors = serializers.ResourceRelatedField(
+        queryset=Author.objects.all(), required=False, many=True
+    )
 
     def validate(self, attrs):
         body_text = attrs["body_text"]
@@ -195,7 +198,31 @@ def test_many_third_level_dict_errors(client, some_blog, snapshot):
     assert snapshot == perform_error_test(client, data)
 
 
-def test_relationship_errors_has_correct_pointers(client, some_blog, snapshot):
+def test_relationship_errors_has_correct_pointers_with_camelize(
+    client, some_blog, snapshot
+):
+    data = {
+        "data": {
+            "type": "entries",
+            "attributes": {
+                "blog": some_blog.pk,
+                "bodyText": "body_text",
+                "headline": "headline",
+            },
+            "relationships": {
+                "mainAuthor": {"data": {"id": "INVALID_ID", "type": "authors"}},
+                "authors": {"data": [{"id": "INVALID_ID", "type": "authors"}]},
+            },
+        }
+    }
+
+    assert snapshot == perform_error_test(client, data)
+
+
+@override_settings(JSON_API_FORMAT_FIELD_NAMES="dasherize")
+def test_relationship_errors_has_correct_pointers_with_dasherize(
+    client, some_blog, snapshot
+):
     data = {
         "data": {
             "type": "entries",
@@ -205,7 +232,30 @@ def test_relationship_errors_has_correct_pointers(client, some_blog, snapshot):
                 "headline": "headline",
             },
             "relationships": {
-                "author": {"data": {"id": "INVALID_ID", "type": "authors"}}
+                "main-author": {"data": {"id": "INVALID_ID", "type": "authors"}},
+                "authors": {"data": [{"id": "INVALID_ID", "type": "authors"}]},
+            },
+        }
+    }
+
+    assert snapshot == perform_error_test(client, data)
+
+
+@override_settings(JSON_API_FORMAT_FIELD_NAMES=None)
+def test_relationship_errors_has_correct_pointers_with_no_formatting(
+    client, some_blog, snapshot
+):
+    data = {
+        "data": {
+            "type": "entries",
+            "attributes": {
+                "blog": some_blog.pk,
+                "body_text": "body_text",
+                "headline": "headline",
+            },
+            "relationships": {
+                "main_author": {"data": {"id": "INVALID_ID", "type": "authors"}},
+                "authors": {"data": [{"id": "INVALID_ID", "type": "authors"}]},
             },
         }
     }