mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-08-13 16:54:47 +03:00
Add more precise validation check for duration field format and adjust docs
This commit is contained in:
parent
a3096b9989
commit
aae5465700
|
@ -317,11 +317,11 @@ Default: `['iso-8601']`
|
||||||
|
|
||||||
#### DURATION_FORMAT
|
#### 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'`
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
@ -1357,11 +1357,16 @@ class DurationField(Field):
|
||||||
if format is not empty:
|
if format is not empty:
|
||||||
if format is None or (isinstance(format, str) and format.lower() in (ISO_8601, DJANGO_DURATION_FORMAT)):
|
if format is None or (isinstance(format, str) and format.lower() in (ISO_8601, DJANGO_DURATION_FORMAT)):
|
||||||
self.format = format
|
self.format = format
|
||||||
else:
|
elif isinstance(format, str):
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Unknown duration format provided, got '{format}'"
|
f"Unknown duration format provided, got '{format}'"
|
||||||
" while expecting 'django', 'iso-8601' or `None`."
|
" 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)
|
super().__init__(**kwargs)
|
||||||
if self.max_value is not None:
|
if self.max_value is not None:
|
||||||
message = lazy_format(self.error_messages['max_value'], max_value=self.max_value)
|
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:
|
if output_format.lower() == DJANGO_DURATION_FORMAT:
|
||||||
return duration_string(value)
|
return duration_string(value)
|
||||||
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"Unknown duration format provided, got '{output_format}'"
|
f"Unknown duration format provided, got '{output_format}'"
|
||||||
" while expecting 'django', 'iso-8601' or `None`."
|
" while expecting 'django', 'iso-8601' or `None`."
|
||||||
|
)
|
||||||
|
raise TypeError(
|
||||||
|
"duration format must be either str or `None`,"
|
||||||
|
f" not {type(output_format).__name__}"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1779,24 +1779,29 @@ class TestDurationField(FieldValues):
|
||||||
"Unknown duration format provided, got 'unknown'"
|
"Unknown duration format provided, got 'unknown'"
|
||||||
" while expecting 'django', 'iso-8601' or `None`."
|
" 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)
|
serializers.DurationField(format=123)
|
||||||
assert str(exc_info.value) == (
|
assert str(exc_info.value) == (
|
||||||
"Unknown duration format provided, got '123'"
|
"duration format must be either str or `None`, not int"
|
||||||
" while expecting 'django', 'iso-8601' or `None`."
|
|
||||||
)
|
)
|
||||||
|
|
||||||
@override_settings(REST_FRAMEWORK={'DURATION_FORMAT': 'unknown'})
|
|
||||||
def test_invalid_format_in_config(self):
|
def test_invalid_format_in_config(self):
|
||||||
field = serializers.DurationField()
|
field = serializers.DurationField()
|
||||||
|
|
||||||
with pytest.raises(ValueError) as exc_info:
|
with override_settings(REST_FRAMEWORK={'DURATION_FORMAT': 'unknown'}):
|
||||||
field.to_representation(datetime.timedelta(days=1))
|
with pytest.raises(ValueError) as exc_info:
|
||||||
|
field.to_representation(datetime.timedelta(days=1))
|
||||||
|
|
||||||
assert str(exc_info.value) == (
|
assert str(exc_info.value) == (
|
||||||
"Unknown duration format provided, got 'unknown'"
|
"Unknown duration format provided, got 'unknown'"
|
||||||
" while expecting 'django', 'iso-8601' or `None`."
|
" 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):
|
class TestNoOutputFormatDurationField(FieldValues):
|
||||||
|
|
Loading…
Reference in New Issue
Block a user