Commit f208d8d2 by Stephan Groß

Add drf settings + output format + testcases

parent ef5752f8
...@@ -13,12 +13,12 @@ from django import forms ...@@ -13,12 +13,12 @@ from django import forms
from django.forms import widgets from django.forms import widgets
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.compat import parse_date, parse_datetime
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
from rest_framework.compat import smart_text from rest_framework.compat import smart_text
from rest_framework.compat import parse_time from rest_framework.settings import api_settings
from rest_framework.utils.dates import get_readable_date_format from rest_framework.utils.dates import get_readable_date_format
...@@ -453,7 +453,8 @@ class DateField(WritableField): ...@@ -453,7 +453,8 @@ class DateField(WritableField):
empty = None empty = None
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.format = kwargs.pop('format', settings.DATE_INPUT_FORMATS) self.input_formats = kwargs.pop('input_formats', api_settings.DATE_INPUT_FORMATS)
self.output_format = kwargs.pop('output_format', api_settings.DATE_OUTPUT_FORMAT)
super(DateField, self).__init__(*args, **kwargs) super(DateField, self).__init__(*args, **kwargs)
def from_native(self, value): def from_native(self, value):
...@@ -470,7 +471,7 @@ class DateField(WritableField): ...@@ -470,7 +471,7 @@ class DateField(WritableField):
if isinstance(value, datetime.date): if isinstance(value, datetime.date):
return value return value
for format in self.format: for format in self.input_formats:
try: try:
parsed = datetime.datetime.strptime(value, format) parsed = datetime.datetime.strptime(value, format)
except (ValueError, TypeError): except (ValueError, TypeError):
...@@ -478,10 +479,15 @@ class DateField(WritableField): ...@@ -478,10 +479,15 @@ class DateField(WritableField):
else: else:
return parsed.date() return parsed.date()
date_input_formats = '; '.join(self.format) date_input_formats = '; '.join(self.input_formats)
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):
if self.output_format is not None:
return value.strftime(self.output_format)
return value.isoformat()
class DateTimeField(WritableField): class DateTimeField(WritableField):
type_name = 'DateTimeField' type_name = 'DateTimeField'
...@@ -494,7 +500,8 @@ class DateTimeField(WritableField): ...@@ -494,7 +500,8 @@ class DateTimeField(WritableField):
empty = None empty = None
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.format = kwargs.pop('format', settings.DATETIME_INPUT_FORMATS) self.input_formats = kwargs.pop('input_formats', api_settings.DATETIME_INPUT_FORMATS)
self.output_format = kwargs.pop('output_format', api_settings.DATETIME_OUTPUT_FORMAT)
super(DateTimeField, self).__init__(*args, **kwargs) super(DateTimeField, self).__init__(*args, **kwargs)
def from_native(self, value): def from_native(self, value):
...@@ -517,7 +524,7 @@ class DateTimeField(WritableField): ...@@ -517,7 +524,7 @@ class DateTimeField(WritableField):
value = timezone.make_aware(value, default_timezone) value = timezone.make_aware(value, default_timezone)
return value return value
for format in self.format: for format in self.input_formats:
try: try:
parsed = datetime.datetime.strptime(value, format) parsed = datetime.datetime.strptime(value, format)
except (ValueError, TypeError): except (ValueError, TypeError):
...@@ -525,10 +532,15 @@ class DateTimeField(WritableField): ...@@ -525,10 +532,15 @@ class DateTimeField(WritableField):
else: else:
return parsed return parsed
datetime_input_formats = '; '.join(self.format) datetime_input_formats = '; '.join(self.input_formats)
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):
if self.output_format is not None:
return value.strftime(self.output_format)
return value.isoformat()
class TimeField(WritableField): class TimeField(WritableField):
type_name = 'TimeField' type_name = 'TimeField'
...@@ -541,7 +553,8 @@ class TimeField(WritableField): ...@@ -541,7 +553,8 @@ class TimeField(WritableField):
empty = None empty = None
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.format = kwargs.pop('format', settings.TIME_INPUT_FORMATS) self.input_formats = kwargs.pop('input_formats', api_settings.TIME_INPUT_FORMATS)
self.output_format = kwargs.pop('output_format', api_settings.TIME_OUTPUT_FORMAT)
super(TimeField, self).__init__(*args, **kwargs) super(TimeField, self).__init__(*args, **kwargs)
def from_native(self, value): def from_native(self, value):
...@@ -551,7 +564,7 @@ class TimeField(WritableField): ...@@ -551,7 +564,7 @@ class TimeField(WritableField):
if isinstance(value, datetime.time): if isinstance(value, datetime.time):
return value return value
for format in self.format: for format in self.input_formats:
try: try:
parsed = datetime.datetime.strptime(value, format) parsed = datetime.datetime.strptime(value, format)
except (ValueError, TypeError): except (ValueError, TypeError):
...@@ -559,10 +572,15 @@ class TimeField(WritableField): ...@@ -559,10 +572,15 @@ class TimeField(WritableField):
else: else:
return parsed.time() return parsed.time()
time_input_formats = '; '.join(self.format) time_input_formats = '; '.join(self.input_formats)
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):
if self.output_format is not None:
return value.strftime(self.output_format)
return value.isoformat()
class IntegerField(WritableField): class IntegerField(WritableField):
type_name = 'IntegerField' type_name = 'IntegerField'
......
...@@ -76,6 +76,27 @@ DEFAULTS = { ...@@ -76,6 +76,27 @@ DEFAULTS = {
'URL_FORMAT_OVERRIDE': 'format', 'URL_FORMAT_OVERRIDE': 'format',
'FORMAT_SUFFIX_KWARG': 'format', 'FORMAT_SUFFIX_KWARG': 'format',
# Input and output formats
'DATE_INPUT_FORMATS': (
'%Y-%m-%d', # '1984-07-31'
),
'DATE_OUTPUT_FORMAT': None,
'DATETIME_INPUT_FORMATS': (
'%Y-%m-%d', # '1984-07-31'
'%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,
'TIME_INPUT_FORMATS': (
'%H:%M', # '04:31'
'%H:%M:%S', # '04:31:59'
'%H:%M:%S.%f', # '04:31:59.000200'
),
'TIME_OUTPUT_FORMAT': None,
} }
......
...@@ -65,8 +65,8 @@ class IntegrationTestFiltering(TestCase): ...@@ -65,8 +65,8 @@ class IntegrationTestFiltering(TestCase):
self.objects = FilterableItem.objects self.objects = FilterableItem.objects
self.data = [ self.data = [
{'id': obj.id, 'text': obj.text, 'decimal': obj.decimal, 'date': obj.date} {'id': obj.id, 'text': obj.text, 'decimal': obj.decimal, 'date': obj.date.isoformat()}
for obj in self.objects.all() for obj in self.objects.all()
] ]
@unittest.skipUnless(django_filters, 'django-filters not installed') @unittest.skipUnless(django_filters, 'django-filters not installed')
...@@ -95,7 +95,7 @@ class IntegrationTestFiltering(TestCase): ...@@ -95,7 +95,7 @@ class IntegrationTestFiltering(TestCase):
request = factory.get('/?date=%s' % search_date) # search_date str: '2012-09-22' request = factory.get('/?date=%s' % search_date) # search_date str: '2012-09-22'
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
expected_data = [f for f in self.data if f['date'] == search_date] expected_data = [f for f in self.data if datetime.datetime.strptime(f['date'], '%Y-%m-%d').date() == search_date]
self.assertEqual(response.data, expected_data) self.assertEqual(response.data, expected_data)
@unittest.skipUnless(django_filters, 'django-filters not installed') @unittest.skipUnless(django_filters, 'django-filters not installed')
...@@ -125,7 +125,7 @@ class IntegrationTestFiltering(TestCase): ...@@ -125,7 +125,7 @@ class IntegrationTestFiltering(TestCase):
request = factory.get('/?date=%s' % search_date) # search_date str: '2012-10-02' request = factory.get('/?date=%s' % search_date) # search_date str: '2012-10-02'
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
expected_data = [f for f in self.data if f['date'] > search_date] expected_data = [f for f in self.data if datetime.datetime.strptime(f['date'], '%Y-%m-%d').date() > search_date]
self.assertEqual(response.data, expected_data) self.assertEqual(response.data, expected_data)
# Tests that the text filter set with 'icontains' in the filter class works. # Tests that the text filter set with 'icontains' in the filter class works.
...@@ -142,8 +142,9 @@ class IntegrationTestFiltering(TestCase): ...@@ -142,8 +142,9 @@ class IntegrationTestFiltering(TestCase):
request = factory.get('/?decimal=%s&date=%s' % (search_decimal, search_date)) request = factory.get('/?decimal=%s&date=%s' % (search_decimal, search_date))
response = view(request).render() response = view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK) self.assertEqual(response.status_code, status.HTTP_200_OK)
expected_data = [f for f in self.data if f['date'] > search_date and expected_data = [f for f in self.data if
f['decimal'] < search_decimal] datetime.datetime.strptime(f['date'], '%Y-%m-%d').date() > search_date and
f['decimal'] < search_decimal]
self.assertEqual(response.data, expected_data) self.assertEqual(response.data, expected_data)
@unittest.skipUnless(django_filters, 'django-filters not installed') @unittest.skipUnless(django_filters, 'django-filters not installed')
......
...@@ -112,8 +112,8 @@ class IntegrationTestPaginationAndFiltering(TestCase): ...@@ -112,8 +112,8 @@ class IntegrationTestPaginationAndFiltering(TestCase):
self.objects = FilterableItem.objects self.objects = FilterableItem.objects
self.data = [ self.data = [
{'id': obj.id, 'text': obj.text, 'decimal': obj.decimal, 'date': obj.date} {'id': obj.id, 'text': obj.text, 'decimal': obj.decimal, 'date': obj.date.isoformat()}
for obj in self.objects.all() for obj in self.objects.all()
] ]
self.view = FilterFieldsRootView.as_view() self.view = FilterFieldsRootView.as_view()
......
...@@ -112,7 +112,7 @@ class BasicTests(TestCase): ...@@ -112,7 +112,7 @@ class BasicTests(TestCase):
self.expected = { self.expected = {
'email': 'tom@example.com', 'email': 'tom@example.com',
'content': 'Happy new year!', 'content': 'Happy new year!',
'created': datetime.datetime(2012, 1, 1), 'created': '2012-01-01T00:00:00',
'sub_comment': 'And Merry Christmas!' 'sub_comment': 'And Merry Christmas!'
} }
self.person_data = {'name': 'dwight', 'age': 35} self.person_data = {'name': 'dwight', 'age': 35}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment