diff --git a/docs/api-guide/settings.md b/docs/api-guide/settings.md index 8d0beb635..66e1131c9 100644 --- a/docs/api-guide/settings.md +++ b/docs/api-guide/settings.md @@ -317,11 +317,11 @@ Default: `['iso-8601']` #### DURATION_FORMAT -A format string that should be used by default for rendering the output of `DurationField` serializer fields. If `None`, then `DurationField` serializer fields will return Python `timedelta` objects, and the duration encoding will be determined by the renderer. +Indicates the default format thath should be used for rendering the output of `DurationField` serializer fields. If `None`, then `DurationField` serializer fields will return Python `timedelta` objects, and the duration encoding will be determined by the renderer. -May be any of `None`, `'iso-8601'` or `'standard'` (the format accepted by `django.utils.dateparse.parse_duration`). +May be any of `None`, `'iso-8601'` or `'django'` (the format accepted by `django.utils.dateparse.parse_duration`). -Default: `'standard'` +Default: `'django'` --- diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 84363f97e..847ee7b19 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -1357,11 +1357,16 @@ class DurationField(Field): if format is not empty: if format is None or (isinstance(format, str) and format.lower() in (ISO_8601, DJANGO_DURATION_FORMAT)): self.format = format - else: + elif isinstance(format, str): raise ValueError( f"Unknown duration format provided, got '{format}'" " while expecting 'django', 'iso-8601' or `None`." ) + else: + raise TypeError( + "duration format must be either str or `None`," + f" not {type(format).__name__}" + ) super().__init__(**kwargs) if self.max_value is not None: message = lazy_format(self.error_messages['max_value'], max_value=self.max_value) @@ -1396,9 +1401,13 @@ class DurationField(Field): if output_format.lower() == DJANGO_DURATION_FORMAT: return duration_string(value) - raise ValueError( - f"Unknown duration format provided, got '{output_format}'" - " while expecting 'django', 'iso-8601' or `None`." + raise ValueError( + f"Unknown duration format provided, got '{output_format}'" + " while expecting 'django', 'iso-8601' or `None`." + ) + raise TypeError( + "duration format must be either str or `None`," + f" not {type(output_format).__name__}" ) diff --git a/tests/test_fields.py b/tests/test_fields.py index 64130c591..81cdadf05 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1779,24 +1779,29 @@ class TestDurationField(FieldValues): "Unknown duration format provided, got 'unknown'" " while expecting 'django', 'iso-8601' or `None`." ) - with pytest.raises(ValueError) as exc_info: + with pytest.raises(TypeError) as exc_info: serializers.DurationField(format=123) assert str(exc_info.value) == ( - "Unknown duration format provided, got '123'" - " while expecting 'django', 'iso-8601' or `None`." + "duration format must be either str or `None`, not int" ) - @override_settings(REST_FRAMEWORK={'DURATION_FORMAT': 'unknown'}) def test_invalid_format_in_config(self): field = serializers.DurationField() - with pytest.raises(ValueError) as exc_info: - field.to_representation(datetime.timedelta(days=1)) + with override_settings(REST_FRAMEWORK={'DURATION_FORMAT': 'unknown'}): + with pytest.raises(ValueError) as exc_info: + field.to_representation(datetime.timedelta(days=1)) assert str(exc_info.value) == ( "Unknown duration format provided, got 'unknown'" " while expecting 'django', 'iso-8601' or `None`." ) + with override_settings(REST_FRAMEWORK={'DURATION_FORMAT': 123}): + with pytest.raises(TypeError) as exc_info: + field.to_representation(datetime.timedelta(days=1)) + assert str(exc_info.value) == ( + "duration format must be either str or `None`, not int" + ) class TestNoOutputFormatDurationField(FieldValues):