mirror of
				https://github.com/encode/django-rest-framework.git
				synced 2025-10-31 16:07:38 +03:00 
			
		
		
		
	Add new ISO8601 setting + integration
This commit is contained in:
		
							parent
							
								
									7e702439eb
								
							
						
					
					
						commit
						29a54b5a77
					
				|  | @ -4,3 +4,6 @@ VERSION = __version__  # synonym | ||||||
| 
 | 
 | ||||||
| # Header encoding (see RFC5987) | # Header encoding (see RFC5987) | ||||||
| HTTP_HEADER_ENCODING = 'iso-8859-1' | HTTP_HEADER_ENCODING = 'iso-8859-1' | ||||||
|  | 
 | ||||||
|  | # Default input and output format | ||||||
|  | ISO8601 = 'iso-8601' | ||||||
|  | @ -11,9 +11,11 @@ from django.core.exceptions import ValidationError | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django import forms | from django import forms | ||||||
| from django.forms import widgets | from django.forms import widgets | ||||||
|  | from django.utils.dateparse import parse_date, parse_datetime, parse_time | ||||||
| from django.utils.encoding import is_protected_type | from django.utils.encoding import is_protected_type | ||||||
| from django.utils.translation import ugettext_lazy as _ | from django.utils.translation import ugettext_lazy as _ | ||||||
| 
 | 
 | ||||||
|  | from rest_framework import ISO8601 | ||||||
| from rest_framework.compat import timezone | from rest_framework.compat import timezone | ||||||
| from rest_framework.compat import BytesIO | from rest_framework.compat import BytesIO | ||||||
| from rest_framework.compat import six | from rest_framework.compat import six | ||||||
|  | @ -472,21 +474,30 @@ class DateField(WritableField): | ||||||
|             return value |             return value | ||||||
| 
 | 
 | ||||||
|         for format in self.input_formats: |         for format in self.input_formats: | ||||||
|             try: |             if format.lower() == ISO8601: | ||||||
|                 parsed = datetime.datetime.strptime(value, format) |                 try: | ||||||
|             except (ValueError, TypeError): |                     parsed = parse_date(value) | ||||||
|                 pass |                 except (ValueError, TypeError): | ||||||
|  |                     pass | ||||||
|  |                 else: | ||||||
|  |                     if parsed is not None: | ||||||
|  |                         return parsed | ||||||
|             else: |             else: | ||||||
|                 return parsed.date() |                 try: | ||||||
|  |                     parsed = datetime.datetime.strptime(value, format) | ||||||
|  |                 except (ValueError, TypeError): | ||||||
|  |                     pass | ||||||
|  |                 else: | ||||||
|  |                     return parsed.date() | ||||||
| 
 | 
 | ||||||
|         date_input_formats = '; '.join(self.input_formats) |         date_input_formats = '; '.join(self.input_formats).replace(ISO8601, 'YYYY-MM-DD') | ||||||
|         msg = self.error_messages['invalid'] % get_readable_date_format(date_input_formats) |         msg = self.error_messages['invalid'] % get_readable_date_format(date_input_formats) | ||||||
|         raise ValidationError(msg) |         raise ValidationError(msg) | ||||||
| 
 | 
 | ||||||
|     def to_native(self, value): |     def to_native(self, value): | ||||||
|         if self.output_format is not None: |         if self.output_format.lower() == ISO8601: | ||||||
|             return value.strftime(self.output_format) |             return value.isoformat() | ||||||
|         return value.isoformat() |         return value.strftime(self.output_format) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class DateTimeField(WritableField): | class DateTimeField(WritableField): | ||||||
|  | @ -525,21 +536,30 @@ class DateTimeField(WritableField): | ||||||
|             return value |             return value | ||||||
| 
 | 
 | ||||||
|         for format in self.input_formats: |         for format in self.input_formats: | ||||||
|             try: |             if format.lower() == ISO8601: | ||||||
|                 parsed = datetime.datetime.strptime(value, format) |                 try: | ||||||
|             except (ValueError, TypeError): |                     parsed = parse_datetime(value) | ||||||
|                 pass |                 except (ValueError, TypeError): | ||||||
|  |                     pass | ||||||
|  |                 else: | ||||||
|  |                     if parsed is not None: | ||||||
|  |                         return parsed | ||||||
|             else: |             else: | ||||||
|                 return parsed |                 try: | ||||||
|  |                     parsed = datetime.datetime.strptime(value, format) | ||||||
|  |                 except (ValueError, TypeError): | ||||||
|  |                     pass | ||||||
|  |                 else: | ||||||
|  |                     return parsed | ||||||
| 
 | 
 | ||||||
|         datetime_input_formats = '; '.join(self.input_formats) |         datetime_input_formats = '; '.join(self.input_formats).replace(ISO8601, 'YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]') | ||||||
|         msg = self.error_messages['invalid'] % get_readable_date_format(datetime_input_formats) |         msg = self.error_messages['invalid'] % get_readable_date_format(datetime_input_formats) | ||||||
|         raise ValidationError(msg) |         raise ValidationError(msg) | ||||||
| 
 | 
 | ||||||
|     def to_native(self, value): |     def to_native(self, value): | ||||||
|         if self.output_format is not None: |         if self.output_format.lower() == ISO8601: | ||||||
|             return value.strftime(self.output_format) |             return value.isoformat() | ||||||
|         return value.isoformat() |         return value.strftime(self.output_format) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class TimeField(WritableField): | class TimeField(WritableField): | ||||||
|  | @ -565,21 +585,30 @@ class TimeField(WritableField): | ||||||
|             return value |             return value | ||||||
| 
 | 
 | ||||||
|         for format in self.input_formats: |         for format in self.input_formats: | ||||||
|             try: |             if format.lower() == ISO8601: | ||||||
|                 parsed = datetime.datetime.strptime(value, format) |                 try: | ||||||
|             except (ValueError, TypeError): |                     parsed = parse_time(value) | ||||||
|                 pass |                 except (ValueError, TypeError): | ||||||
|  |                     pass | ||||||
|  |                 else: | ||||||
|  |                     if parsed is not None: | ||||||
|  |                         return parsed | ||||||
|             else: |             else: | ||||||
|                 return parsed.time() |                 try: | ||||||
|  |                     parsed = datetime.datetime.strptime(value, format) | ||||||
|  |                 except (ValueError, TypeError): | ||||||
|  |                     pass | ||||||
|  |                 else: | ||||||
|  |                     return parsed.time() | ||||||
| 
 | 
 | ||||||
|         time_input_formats = '; '.join(self.input_formats) |         time_input_formats = '; '.join(self.input_formats).replace(ISO8601, 'HH:MM[:ss[.uuuuuu]]') | ||||||
|         msg = self.error_messages['invalid'] % get_readable_date_format(time_input_formats) |         msg = self.error_messages['invalid'] % get_readable_date_format(time_input_formats) | ||||||
|         raise ValidationError(msg) |         raise ValidationError(msg) | ||||||
| 
 | 
 | ||||||
|     def to_native(self, value): |     def to_native(self, value): | ||||||
|         if self.output_format is not None: |         if self.output_format.lower() == ISO8601: | ||||||
|             return value.strftime(self.output_format) |             return value.isoformat() | ||||||
|         return value.isoformat() |         return value.strftime(self.output_format) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class IntegerField(WritableField): | class IntegerField(WritableField): | ||||||
|  |  | ||||||
|  | @ -18,8 +18,11 @@ REST framework settings, checking for user settings first, then falling | ||||||
| back to the defaults. | back to the defaults. | ||||||
| """ | """ | ||||||
| from __future__ import unicode_literals | from __future__ import unicode_literals | ||||||
|  | 
 | ||||||
| from django.conf import settings | from django.conf import settings | ||||||
| from django.utils import importlib | from django.utils import importlib | ||||||
|  | 
 | ||||||
|  | from rest_framework import ISO8601 | ||||||
| from rest_framework.compat import six | from rest_framework.compat import six | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -79,24 +82,19 @@ DEFAULTS = { | ||||||
| 
 | 
 | ||||||
|     # Input and output formats |     # Input and output formats | ||||||
|     'DATE_INPUT_FORMATS': ( |     'DATE_INPUT_FORMATS': ( | ||||||
|         '%Y-%m-%d',     # '1984-07-31' |         ISO8601, | ||||||
|     ), |     ), | ||||||
|     'DATE_OUTPUT_FORMAT': None, |     'DATE_OUTPUT_FORMAT': ISO8601, | ||||||
| 
 | 
 | ||||||
|     'DATETIME_INPUT_FORMATS': ( |     'DATETIME_INPUT_FORMATS': ( | ||||||
|         '%Y-%m-%d',              # '1984-07-31' |         ISO8601, | ||||||
|         '%Y-%m-%d %H:%M',        # '1984-07-31 04:31' |  | ||||||
|         '%Y-%m-%d %H:%M:%S',     # '1984-07-31 04:31:59' |  | ||||||
|         '%Y-%m-%d %H:%M:%S.%f',  # '1984-07-31 04:31:59.000200' |  | ||||||
|     ), |     ), | ||||||
|     'DATETIME_OUTPUT_FORMAT': None, |     'DATETIME_OUTPUT_FORMAT': ISO8601, | ||||||
| 
 | 
 | ||||||
|     'TIME_INPUT_FORMATS': ( |     'TIME_INPUT_FORMATS': ( | ||||||
|         '%H:%M',        # '04:31' |         ISO8601, | ||||||
|         '%H:%M:%S',     # '04:31:59' |  | ||||||
|         '%H:%M:%S.%f',  # '04:31:59.000200' |  | ||||||
|     ), |     ), | ||||||
|     'TIME_OUTPUT_FORMAT': None, |     'TIME_OUTPUT_FORMAT': ISO8601, | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -173,30 +173,26 @@ class DateTimeFieldTest(TestCase): | ||||||
|         Make sure from_native() accepts default iso input formats. |         Make sure from_native() accepts default iso input formats. | ||||||
|         """ |         """ | ||||||
|         f = serializers.DateTimeField() |         f = serializers.DateTimeField() | ||||||
|         result_1 = f.from_native('1984-07-31') |         result_1 = f.from_native('1984-07-31 04:31') | ||||||
|         result_2 = f.from_native('1984-07-31 04:31') |         result_2 = f.from_native('1984-07-31 04:31:59') | ||||||
|         result_3 = f.from_native('1984-07-31 04:31:59') |         result_3 = f.from_native('1984-07-31 04:31:59.000200') | ||||||
|         result_4 = f.from_native('1984-07-31 04:31:59.000200') |  | ||||||
| 
 | 
 | ||||||
|         self.assertEqual(datetime.datetime(1984, 7, 31), result_1) |         self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31), result_1) | ||||||
|         self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31), result_2) |         self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59), result_2) | ||||||
|         self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59), result_3) |         self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59, 200), result_3) | ||||||
|         self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59, 200), result_4) |  | ||||||
| 
 | 
 | ||||||
|     def test_from_native_datetime_datetime(self): |     def test_from_native_datetime_datetime(self): | ||||||
|         """ |         """ | ||||||
|         Make sure from_native() accepts a datetime.datetime instance. |         Make sure from_native() accepts a datetime.datetime instance. | ||||||
|         """ |         """ | ||||||
|         f = serializers.DateTimeField() |         f = serializers.DateTimeField() | ||||||
|         result_1 = f.from_native(datetime.datetime(1984, 7, 31)) |         result_1 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31)) | ||||||
|         result_2 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31)) |         result_2 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31, 59)) | ||||||
|         result_3 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31, 59)) |         result_3 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31, 59, 200)) | ||||||
|         result_4 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31, 59, 200)) |  | ||||||
| 
 | 
 | ||||||
|         self.assertEqual(result_1, datetime.datetime(1984, 7, 31)) |         self.assertEqual(result_1, datetime.datetime(1984, 7, 31, 4, 31)) | ||||||
|         self.assertEqual(result_2, datetime.datetime(1984, 7, 31, 4, 31)) |         self.assertEqual(result_2, datetime.datetime(1984, 7, 31, 4, 31, 59)) | ||||||
|         self.assertEqual(result_3, datetime.datetime(1984, 7, 31, 4, 31, 59)) |         self.assertEqual(result_3, datetime.datetime(1984, 7, 31, 4, 31, 59, 200)) | ||||||
|         self.assertEqual(result_4, datetime.datetime(1984, 7, 31, 4, 31, 59, 200)) |  | ||||||
| 
 | 
 | ||||||
|     def test_from_native_custom_format(self): |     def test_from_native_custom_format(self): | ||||||
|         """ |         """ | ||||||
|  | @ -239,8 +235,7 @@ class DateTimeFieldTest(TestCase): | ||||||
|             f.from_native('04:61:59') |             f.from_native('04:61:59') | ||||||
|         except validators.ValidationError as e: |         except validators.ValidationError as e: | ||||||
|             self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: " |             self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: " | ||||||
|                                           "YYYY-MM-DD; YYYY-MM-DD HH:MM; YYYY-MM-DD HH:MM:SS; " |                                           "YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]"]) | ||||||
|                                           "YYYY-MM-DD HH:MM:SS.uuuuuu"]) |  | ||||||
|         else: |         else: | ||||||
|             self.fail("ValidationError was not properly raised") |             self.fail("ValidationError was not properly raised") | ||||||
| 
 | 
 | ||||||
|  | @ -254,8 +249,7 @@ class DateTimeFieldTest(TestCase): | ||||||
|             f.from_native('04 -- 31') |             f.from_native('04 -- 31') | ||||||
|         except validators.ValidationError as e: |         except validators.ValidationError as e: | ||||||
|             self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: " |             self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: " | ||||||
|                                           "YYYY-MM-DD; YYYY-MM-DD HH:MM; YYYY-MM-DD HH:MM:SS; " |                                           "YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]"]) | ||||||
|                                           "YYYY-MM-DD HH:MM:SS.uuuuuu"]) |  | ||||||
|         else: |         else: | ||||||
|             self.fail("ValidationError was not properly raised") |             self.fail("ValidationError was not properly raised") | ||||||
| 
 | 
 | ||||||
|  | @ -364,7 +358,7 @@ class TimeFieldTest(TestCase): | ||||||
|             f.from_native('04:61:59') |             f.from_native('04:61:59') | ||||||
|         except validators.ValidationError as e: |         except validators.ValidationError as e: | ||||||
|             self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: " |             self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: " | ||||||
|                                           "HH:MM; HH:MM:SS; HH:MM:SS.uuuuuu"]) |                                           "HH:MM[:ss[.uuuuuu]]"]) | ||||||
|         else: |         else: | ||||||
|             self.fail("ValidationError was not properly raised") |             self.fail("ValidationError was not properly raised") | ||||||
| 
 | 
 | ||||||
|  | @ -378,7 +372,7 @@ class TimeFieldTest(TestCase): | ||||||
|             f.from_native('04 -- 31') |             f.from_native('04 -- 31') | ||||||
|         except validators.ValidationError as e: |         except validators.ValidationError as e: | ||||||
|             self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: " |             self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: " | ||||||
|                                           "HH:MM; HH:MM:SS; HH:MM:SS.uuuuuu"]) |                                           "HH:MM[:ss[.uuuuuu]]"]) | ||||||
|         else: |         else: | ||||||
|             self.fail("ValidationError was not properly raised") |             self.fail("ValidationError was not properly raised") | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user