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

Issue:
Resolve resource type in serializer's meta class
`utils.get_resource_type_from_serializer` is called several times throughout the DJA code base. When this method raises an `AttributeError` it is a configuration/code setup issue and not a runtime issue. Besides there is no error message describing want went wrong.

Goals:
* move logic of `get_resource_type_from_serializer` to serializer's meta class
* improve error handling (better error message).

Discussion:

Patch:
diff --git a/AUTHORS b/AUTHORS
index 35d959c..fa91e9b 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -15,6 +15,7 @@ Jamie Bliss <astronouth7303@gmail.com>
 Jason Housley <housleyjk@gmail.com>
 Jeppe Fihl-Pearson <jeppe@tenzer.dk>
 Jerel Unruh <mail@unruhdesigns.com>
+Jonas Kiefer <https://github.com/jokiefer>
 Jonas Metzener <jonas.metzener@adfinis.com>
 Jonathan Senecal <contact@jonathansenecal.com>
 Joseba Mendivil <git@jma.email>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 10559dd..1fa3d92 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ any parts of the framework not mentioned in the documentation should generally b
 * Raise comprehensible error when reserved field names `meta` and `results` are used.
 * Use `relationships` in the error object `pointer` when the field is actually a relationship.
 * Added missing inflection to the generated OpenAPI schema.
+* Added missing error message when `resource_name` is not properly configured.
 
 ### Changed
 
diff --git a/rest_framework_json_api/utils.py b/rest_framework_json_api/utils.py
index 65cbc64..6189093 100644
--- a/rest_framework_json_api/utils.py
+++ b/rest_framework_json_api/utils.py
@@ -320,7 +320,10 @@ def get_resource_type_from_serializer(serializer):
         return meta.resource_name
     elif hasattr(meta, "model"):
         return get_resource_type_from_model(meta.model)
-    raise AttributeError()
+    raise AttributeError(
+        f"can not detect 'resource_name' on serializer '{serializer.__class__.__name__}'"
+        f" in module '{serializer.__class__.__module__}'"
+    )
 
 
 def get_included_resources(request, serializer=None):


Test patch:
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 43c12dc..d8810c0 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -1,6 +1,7 @@
 import pytest
 from django.db import models
 from rest_framework import status
+from rest_framework.fields import Field
 from rest_framework.generics import GenericAPIView
 from rest_framework.response import Response
 from rest_framework.views import APIView
@@ -15,6 +16,7 @@ from rest_framework_json_api.utils import (
     get_included_serializers,
     get_related_resource_type,
     get_resource_name,
+    get_resource_type_from_serializer,
     undo_format_field_name,
     undo_format_field_names,
     undo_format_link_segment,
@@ -377,3 +379,17 @@ def test_get_included_serializers():
     }
 
     assert included_serializers == expected_included_serializers
+
+
+def test_get_resource_type_from_serializer_without_resource_name_raises_error():
+    class SerializerWithoutResourceName(serializers.Serializer):
+        something = Field()
+
+    serializer = SerializerWithoutResourceName()
+
+    with pytest.raises(AttributeError) as excinfo:
+        get_resource_type_from_serializer(serializer=serializer)
+    assert str(excinfo.value) == (
+        "can not detect 'resource_name' on serializer "
+        "'SerializerWithoutResourceName' in module 'tests.test_utils'"
+    )