Skip to content

Commit 6c5339a

Browse files
committed
Handle unset fields with 'many=True'
The docs note: When serializing fields with dotted notation, it may be necessary to provide a `default` value if any object is not present or is empty during attribute traversal. However, this doesn't work for fields with 'many=True'. When using these, the default is simply ignored. The solution is simple: do in 'ManyRelatedField' what we were already doing for 'Field', namely, catch possible 'AttributeError' and 'KeyError' exceptions and return the default if there is one set. Signed-off-by: Stephen Finucane <stephen@that.guru> Closes: #7550
1 parent 91916a4 commit 6c5339a

File tree

1 file changed

+25
-2
lines changed

1 file changed

+25
-2
lines changed

rest_framework/relations.py

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from django.utils.translation import gettext_lazy as _
1111

1212
from rest_framework.fields import (
13-
Field, empty, get_attribute, is_simple_callable, iter_options
13+
Field, SkipField, empty, get_attribute, is_simple_callable, iter_options
1414
)
1515
from rest_framework.reverse import reverse
1616
from rest_framework.settings import api_settings
@@ -531,7 +531,30 @@ def get_attribute(self, instance):
531531
if hasattr(instance, 'pk') and instance.pk is None:
532532
return []
533533

534-
relationship = get_attribute(instance, self.source_attrs)
534+
try:
535+
relationship = get_attribute(instance, self.source_attrs)
536+
except (KeyError, AttributeError) as exc:
537+
if self.default is not empty:
538+
return self.get_default()
539+
if self.allow_null:
540+
return None
541+
if not self.required:
542+
raise SkipField()
543+
msg = (
544+
'Got {exc_type} when attempting to get a value for field '
545+
'`{field}` on serializer `{serializer}`.\nThe serializer '
546+
'field might be named incorrectly and not match '
547+
'any attribute or key on the `{instance}` instance.\n'
548+
'Original exception text was: {exc}.'.format(
549+
exc_type=type(exc).__name__,
550+
field=self.field_name,
551+
serializer=self.parent.__class__.__name__,
552+
instance=instance.__class__.__name__,
553+
exc=exc
554+
)
555+
)
556+
raise type(exc)(msg)
557+
535558
return relationship.all() if hasattr(relationship, 'all') else relationship
536559

537560
def to_representation(self, iterable):

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy