Skip to content

Commit 60e3d02

Browse files
committed
Add relationships support for pointers in errors
Signed-off-by: Mehdy Khoshnoody <[email protected]>
1 parent 29971b4 commit 60e3d02

File tree

2 files changed

+24
-9
lines changed

2 files changed

+24
-9
lines changed

rest_framework_json_api/renderers.py

+3-7
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ def extract_attributes(cls, fields, resource):
6565
if fields[field_name].write_only:
6666
continue
6767
# Skip fields with relations
68-
if isinstance(field, (relations.RelatedField, relations.ManyRelatedField)):
68+
if utils.is_relationship_field(field):
6969
continue
7070

7171
# Skip read_only attribute fields when `resource` is an empty
@@ -105,9 +105,7 @@ def extract_relationships(cls, fields, resource, resource_instance):
105105
continue
106106

107107
# Skip fields without relations
108-
if not isinstance(
109-
field, (relations.RelatedField, relations.ManyRelatedField)
110-
):
108+
if not utils.is_relationship_field(field):
111109
continue
112110

113111
source = field.source
@@ -298,9 +296,7 @@ def extract_included(
298296
continue
299297

300298
# Skip fields without relations
301-
if not isinstance(
302-
field, (relations.RelatedField, relations.ManyRelatedField)
303-
):
299+
if not utils.is_relationship_field(field):
304300
continue
305301

306302
try:

rest_framework_json_api/utils.py

+21-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
from django.http import Http404
1414
from django.utils import encoding
1515
from django.utils.translation import gettext_lazy as _
16-
from rest_framework import exceptions
16+
from rest_framework import exceptions, relations
1717
from rest_framework.exceptions import APIException
1818

1919
from .settings import json_api_settings
@@ -368,6 +368,10 @@ def get_relation_instance(resource_instance, source, serializer):
368368
return True, relation_instance
369369

370370

371+
def is_relationship_field(field):
372+
return isinstance(field, (relations.RelatedField, relations.ManyRelatedField))
373+
374+
371375
class Hyperlink(str):
372376
"""
373377
A string like object that additionally has an associated name.
@@ -394,9 +398,24 @@ def format_drf_errors(response, context, exc):
394398
errors.extend(format_error_object(message, "/data", response))
395399
# handle all errors thrown from serializers
396400
else:
401+
# Avoid circular deps
402+
from rest_framework import generics
403+
404+
has_serializer = isinstance(context["view"], generics.GenericAPIView)
405+
if has_serializer:
406+
serializer = context["view"].get_serializer()
407+
fields = get_serializer_fields(serializer) or dict()
408+
relationship_fields = [
409+
name for name, field in fields.items() if is_relationship_field(field)
410+
]
411+
397412
for field, error in response.data.items():
398413
field = format_field_name(field)
399-
pointer = "/data/attributes/{}".format(field)
414+
pointer = None
415+
# pointer can be determined only if there's a serializer.
416+
if has_serializer:
417+
rel = "relationships" if field in relationship_fields else "attributes"
418+
pointer = "/data/{}/{}".format(rel, field)
400419
if isinstance(exc, Http404) and isinstance(error, str):
401420
# 404 errors don't have a pointer
402421
errors.extend(format_error_object(error, None, response))

0 commit comments

Comments
 (0)