Coerce dates etc to ISO_8601 in seralizer, by default.

This commit is contained in:
Tom Christie 2014-09-12 12:10:22 +01:00
parent 22af49bf8f
commit 79715f01f8
4 changed files with 31 additions and 33 deletions

View File

@ -431,10 +431,12 @@ class DecimalField(Field):
'max_whole_digits': _('Ensure that there are no more than {max_whole_digits} digits before the decimal point.') 'max_whole_digits': _('Ensure that there are no more than {max_whole_digits} digits before the decimal point.')
} }
def __init__(self, max_digits, decimal_places, coerce_to_string=True, max_value=None, min_value=None, **kwargs): coerce_to_string = api_settings.COERCE_DECIMAL_TO_STRING
def __init__(self, max_digits, decimal_places, coerce_to_string=None, max_value=None, min_value=None, **kwargs):
self.max_digits = max_digits self.max_digits = max_digits
self.decimal_places = decimal_places self.decimal_places = decimal_places
self.coerce_to_string = coerce_to_string self.coerce_to_string = coerce_to_string if (coerce_to_string is not None) else self.coerce_to_string
super(DecimalField, self).__init__(**kwargs) super(DecimalField, self).__init__(**kwargs)
if max_value is not None: if max_value is not None:
self.validators.append(validators.MaxValueValidator(max_value)) self.validators.append(validators.MaxValueValidator(max_value))
@ -510,12 +512,12 @@ class DateField(Field):
default_error_messages = { default_error_messages = {
'invalid': _('Date has wrong format. Use one of these formats instead: {format}'), 'invalid': _('Date has wrong format. Use one of these formats instead: {format}'),
} }
input_formats = api_settings.DATE_INPUT_FORMATS
format = api_settings.DATE_FORMAT format = api_settings.DATE_FORMAT
input_formats = api_settings.DATE_INPUT_FORMATS
def __init__(self, input_formats=None, format=None, *args, **kwargs): def __init__(self, format=None, input_formats=None, *args, **kwargs):
self.input_formats = input_formats if input_formats is not None else self.input_formats
self.format = format if format is not None else self.format self.format = format if format is not None else self.format
self.input_formats = input_formats if input_formats is not None else self.input_formats
super(DateField, self).__init__(*args, **kwargs) super(DateField, self).__init__(*args, **kwargs)
def to_internal_value(self, value): def to_internal_value(self, value):
@ -569,12 +571,12 @@ class DateTimeField(Field):
default_error_messages = { default_error_messages = {
'invalid': _('Datetime has wrong format. Use one of these formats instead: {format}'), 'invalid': _('Datetime has wrong format. Use one of these formats instead: {format}'),
} }
input_formats = api_settings.DATETIME_INPUT_FORMATS
format = api_settings.DATETIME_FORMAT format = api_settings.DATETIME_FORMAT
input_formats = api_settings.DATETIME_INPUT_FORMATS
def __init__(self, input_formats=None, format=None, *args, **kwargs): def __init__(self, format=None, input_formats=None, *args, **kwargs):
self.input_formats = input_formats if input_formats is not None else self.input_formats
self.format = format if format is not None else self.format self.format = format if format is not None else self.format
self.input_formats = input_formats if input_formats is not None else self.input_formats
super(DateTimeField, self).__init__(*args, **kwargs) super(DateTimeField, self).__init__(*args, **kwargs)
def to_internal_value(self, value): def to_internal_value(self, value):
@ -634,12 +636,12 @@ class TimeField(Field):
default_error_messages = { default_error_messages = {
'invalid': _('Time has wrong format. Use one of these formats instead: {format}'), 'invalid': _('Time has wrong format. Use one of these formats instead: {format}'),
} }
input_formats = api_settings.TIME_INPUT_FORMATS
format = api_settings.TIME_FORMAT format = api_settings.TIME_FORMAT
input_formats = api_settings.TIME_INPUT_FORMATS
def __init__(self, input_formats=None, format=None, *args, **kwargs): def __init__(self, format=None, input_formats=None, *args, **kwargs):
self.input_formats = input_formats if input_formats is not None else self.input_formats
self.format = format if format is not None else self.format self.format = format if format is not None else self.format
self.input_formats = input_formats if input_formats is not None else self.input_formats
super(TimeField, self).__init__(*args, **kwargs) super(TimeField, self).__init__(*args, **kwargs)
def from_native(self, value): def from_native(self, value):

View File

@ -97,24 +97,19 @@ DEFAULTS = {
'URL_FIELD_NAME': 'url', 'URL_FIELD_NAME': 'url',
# Input and output formats # Input and output formats
'DATE_INPUT_FORMATS': ( 'DATE_FORMAT': ISO_8601,
ISO_8601, 'DATE_INPUT_FORMATS': (ISO_8601,),
),
'DATE_FORMAT': None,
'DATETIME_INPUT_FORMATS': ( 'DATETIME_FORMAT': ISO_8601,
ISO_8601, 'DATETIME_INPUT_FORMATS': (ISO_8601,),
),
'DATETIME_FORMAT': None,
'TIME_INPUT_FORMATS': ( 'TIME_FORMAT': ISO_8601,
ISO_8601, 'TIME_INPUT_FORMATS': (ISO_8601,),
),
'TIME_FORMAT': None,
# Encoding # Encoding
'UNICODE_JSON': True, 'UNICODE_JSON': True,
'COMPACT_JSON': True 'COMPACT_JSON': True,
'COERCE_DECIMAL_TO_STRING': True
} }

View File

@ -2,10 +2,11 @@ from __future__ import unicode_literals
import datetime import datetime
from decimal import Decimal from decimal import Decimal
from django.db import models from django.db import models
from django.conf.urls import patterns, url
from django.core.urlresolvers import reverse from django.core.urlresolvers import reverse
from django.test import TestCase from django.test import TestCase
from django.utils import unittest from django.utils import unittest
from django.conf.urls import patterns, url from django.utils.dateparse import parse_date
from rest_framework import generics, serializers, status, filters from rest_framework import generics, serializers, status, filters
from rest_framework.compat import django_filters from rest_framework.compat import django_filters
from rest_framework.test import APIRequestFactory from rest_framework.test import APIRequestFactory
@ -102,7 +103,7 @@ if django_filters:
class CommonFilteringTestCase(TestCase): class CommonFilteringTestCase(TestCase):
def _serialize_object(self, obj): def _serialize_object(self, obj):
return {'id': obj.id, 'text': obj.text, 'decimal': str(obj.decimal), 'date': obj.date} return {'id': obj.id, 'text': obj.text, 'decimal': str(obj.decimal), 'date': obj.date.isoformat()}
def setUp(self): def setUp(self):
""" """
@ -153,7 +154,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
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 parse_date(f['date']) == search_date]
self.assertEqual(response.data, expected_data) self.assertEqual(response.data, expected_data)
@unittest.skipUnless(django_filters, 'django-filter not installed') @unittest.skipUnless(django_filters, 'django-filter not installed')
@ -209,7 +210,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
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 parse_date(f['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.
@ -229,7 +230,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase):
}) })
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 parse_date(f['date']) > search_date and
Decimal(f['decimal']) < search_decimal] Decimal(f['decimal']) < search_decimal]
self.assertEqual(response.data, expected_data) self.assertEqual(response.data, expected_data)
@ -481,9 +482,9 @@ class DjangoFilterOrderingTests(TestCase):
self.assertEqual( self.assertEqual(
response.data, response.data,
[ [
{'id': 3, 'date': datetime.date(2014, 10, 8), 'text': 'cde'}, {'id': 3, 'date': '2014-10-08', 'text': 'cde'},
{'id': 2, 'date': datetime.date(2013, 10, 8), 'text': 'bcd'}, {'id': 2, 'date': '2013-10-08', 'text': 'bcd'},
{'id': 1, 'date': datetime.date(2012, 10, 8), 'text': 'abc'} {'id': 1, 'date': '2012-10-08', 'text': 'abc'}
] ]
) )

View File

@ -135,7 +135,7 @@ class IntegrationTestPaginationAndFiltering(TestCase):
self.objects = FilterableItem.objects self.objects = FilterableItem.objects
self.data = [ self.data = [
{'id': obj.id, 'text': obj.text, 'decimal': str(obj.decimal), 'date': obj.date} {'id': obj.id, 'text': obj.text, 'decimal': str(obj.decimal), 'date': obj.date.isoformat()}
for obj in self.objects.all() for obj in self.objects.all()
] ]