diff --git a/rest_framework/fields.py b/rest_framework/fields.py index 9d96cf5cc..e1855ff74 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -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.') } - 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.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) if max_value is not None: self.validators.append(validators.MaxValueValidator(max_value)) @@ -510,12 +512,12 @@ class DateField(Field): default_error_messages = { 'invalid': _('Date has wrong format. Use one of these formats instead: {format}'), } - input_formats = api_settings.DATE_INPUT_FORMATS format = api_settings.DATE_FORMAT + input_formats = api_settings.DATE_INPUT_FORMATS - def __init__(self, input_formats=None, format=None, *args, **kwargs): - self.input_formats = input_formats if input_formats is not None else self.input_formats + def __init__(self, format=None, input_formats=None, *args, **kwargs): 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) def to_internal_value(self, value): @@ -569,12 +571,12 @@ class DateTimeField(Field): default_error_messages = { 'invalid': _('Datetime has wrong format. Use one of these formats instead: {format}'), } - input_formats = api_settings.DATETIME_INPUT_FORMATS format = api_settings.DATETIME_FORMAT + input_formats = api_settings.DATETIME_INPUT_FORMATS - def __init__(self, input_formats=None, format=None, *args, **kwargs): - self.input_formats = input_formats if input_formats is not None else self.input_formats + def __init__(self, format=None, input_formats=None, *args, **kwargs): 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) def to_internal_value(self, value): @@ -634,12 +636,12 @@ class TimeField(Field): default_error_messages = { 'invalid': _('Time has wrong format. Use one of these formats instead: {format}'), } - input_formats = api_settings.TIME_INPUT_FORMATS format = api_settings.TIME_FORMAT + input_formats = api_settings.TIME_INPUT_FORMATS - def __init__(self, input_formats=None, format=None, *args, **kwargs): - self.input_formats = input_formats if input_formats is not None else self.input_formats + def __init__(self, format=None, input_formats=None, *args, **kwargs): 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) def from_native(self, value): diff --git a/rest_framework/settings.py b/rest_framework/settings.py index e55610bbc..421e146c8 100644 --- a/rest_framework/settings.py +++ b/rest_framework/settings.py @@ -97,24 +97,19 @@ DEFAULTS = { 'URL_FIELD_NAME': 'url', # Input and output formats - 'DATE_INPUT_FORMATS': ( - ISO_8601, - ), - 'DATE_FORMAT': None, + 'DATE_FORMAT': ISO_8601, + 'DATE_INPUT_FORMATS': (ISO_8601,), - 'DATETIME_INPUT_FORMATS': ( - ISO_8601, - ), - 'DATETIME_FORMAT': None, + 'DATETIME_FORMAT': ISO_8601, + 'DATETIME_INPUT_FORMATS': (ISO_8601,), - 'TIME_INPUT_FORMATS': ( - ISO_8601, - ), - 'TIME_FORMAT': None, + 'TIME_FORMAT': ISO_8601, + 'TIME_INPUT_FORMATS': (ISO_8601,), # Encoding 'UNICODE_JSON': True, - 'COMPACT_JSON': True + 'COMPACT_JSON': True, + 'COERCE_DECIMAL_TO_STRING': True } diff --git a/tests/test_filters.py b/tests/test_filters.py index 01668114b..dc84dcbd0 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -2,10 +2,11 @@ from __future__ import unicode_literals import datetime from decimal import Decimal from django.db import models +from django.conf.urls import patterns, url from django.core.urlresolvers import reverse from django.test import TestCase 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.compat import django_filters from rest_framework.test import APIRequestFactory @@ -102,7 +103,7 @@ if django_filters: class CommonFilteringTestCase(TestCase): 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): """ @@ -153,7 +154,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase): request = factory.get('/', {'date': '%s' % search_date}) # search_date str: '2012-09-22' response = view(request).render() 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) @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' response = view(request).render() 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) # Tests that the text filter set with 'icontains' in the filter class works. @@ -229,7 +230,7 @@ class IntegrationTestFiltering(CommonFilteringTestCase): }) response = view(request).render() 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] self.assertEqual(response.data, expected_data) @@ -481,9 +482,9 @@ class DjangoFilterOrderingTests(TestCase): self.assertEqual( response.data, [ - {'id': 3, 'date': datetime.date(2014, 10, 8), 'text': 'cde'}, - {'id': 2, 'date': datetime.date(2013, 10, 8), 'text': 'bcd'}, - {'id': 1, 'date': datetime.date(2012, 10, 8), 'text': 'abc'} + {'id': 3, 'date': '2014-10-08', 'text': 'cde'}, + {'id': 2, 'date': '2013-10-08', 'text': 'bcd'}, + {'id': 1, 'date': '2012-10-08', 'text': 'abc'} ] ) diff --git a/tests/test_pagination.py b/tests/test_pagination.py index a7f8e691f..1fd9cf9c4 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -135,7 +135,7 @@ class IntegrationTestPaginationAndFiltering(TestCase): self.objects = FilterableItem.objects 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() ]