13
13
from django .http import Http404
14
14
from django .utils import encoding
15
15
from django .utils .translation import gettext_lazy as _
16
- from rest_framework import exceptions
16
+ from rest_framework import exceptions , relations
17
17
from rest_framework .exceptions import APIException
18
18
19
19
from .settings import json_api_settings
@@ -368,6 +368,10 @@ def get_relation_instance(resource_instance, source, serializer):
368
368
return True , relation_instance
369
369
370
370
371
+ def is_relationship_field (field ):
372
+ return isinstance (field , (relations .RelatedField , relations .ManyRelatedField ))
373
+
374
+
371
375
class Hyperlink (str ):
372
376
"""
373
377
A string like object that additionally has an associated name.
@@ -394,9 +398,24 @@ def format_drf_errors(response, context, exc):
394
398
errors .extend (format_error_object (message , "/data" , response ))
395
399
# handle all errors thrown from serializers
396
400
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
+
397
412
for field , error in response .data .items ():
398
413
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 )
400
419
if isinstance (exc , Http404 ) and isinstance (error , str ):
401
420
# 404 errors don't have a pointer
402
421
errors .extend (format_error_object (error , None , response ))
0 commit comments