aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/fields.py86
-rw-r--r--rest_framework/serializers.py7
-rw-r--r--rest_framework/tests/fields.py91
-rw-r--r--rest_framework/views.py2
4 files changed, 56 insertions, 130 deletions
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index cdcb0ee9..d5a1394d 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -31,36 +31,6 @@ from rest_framework.compat import smart_text, force_text, is_non_str_iterable
from rest_framework.settings import api_settings
-HUMANIZED_FIELD_TYPES = {
- 'BooleanField': u'Boolean',
- 'CharField': u'String',
- 'ChoiceField': u'Single Choice',
- 'ComboField': u'Single Choice',
- 'DateField': u'Date',
- 'DateTimeField': u'Date and Time',
- 'DecimalField': u'Decimal',
- 'EmailField': u'Email',
- 'Field': u'Field',
- 'FileField': u'File',
- 'FilePathField': u'File Path',
- 'FloatField': u'Float',
- 'GenericIPAddressField': u'Generic IP Address',
- 'IPAddressField': u'IP Address',
- 'ImageField': u'Image',
- 'IntegerField': u'Integer',
- 'MultiValueField': u'Multiple Value',
- 'MultipleChoiceField': u'Multiple Choice',
- 'NullBooleanField': u'Nullable Boolean',
- 'RegexField': u'Regular Expression',
- 'SlugField': u'Slug',
- 'SplitDateTimeField': u'Split Date and Time',
- 'TimeField': u'Time',
- 'TypedChoiceField': u'Typed Single Choice',
- 'TypedMultipleChoiceField': u'Typed Multiple Choice',
- 'URLField': u'URL',
-}
-
-
def is_simple_callable(obj):
"""
True if the object is a callable that takes no arguments.
@@ -102,49 +72,6 @@ def readable_date_formats(formats):
return humanize_strptime(format)
-def humanize_field_type(field_type):
- """Return a human-readable name for a field type.
-
- :param field_type: Either a field type class (for example
- django.forms.fields.DateTimeField), or the name of a field type
- (for example "DateTimeField").
-
- :return: unicode
-
- """
- if isinstance(field_type, basestring):
- field_type_name = field_type
- else:
- field_type_name = field_type.__name__
- try:
- return HUMANIZED_FIELD_TYPES[field_type_name]
- except KeyError:
- humanized = re.sub('([a-z0-9])([A-Z])', r'\1 \2', field_type_name)
- return humanized.capitalize()
-
-
-def humanize_field(field):
- """Return a human-readable description of a field.
-
- :param field: A Django field.
-
- :return: A dictionary of the form {type: type name, required: bool,
- label: field label: read_only: bool,
- help_text: optional help text}
-
- """
- humanized = {
- 'type': humanize_field_type(field.__class__),
- 'required': getattr(field, 'required', False),
- }
- optional_attrs = ['read_only', 'help_text', 'label',
- 'min_length', 'max_length']
- for attr in optional_attrs:
- if getattr(field, attr, None) is not None:
- humanized[attr] = getattr(field, attr)
- return humanized
-
-
def humanize_form_fields(form):
"""Return a humanized description of all the fields in a form.
@@ -274,6 +201,19 @@ class Field(object):
return {'type': self.type_name}
return {}
+ @property
+ def humanized(self):
+ humanized = {
+ 'type': self.type_name,
+ 'required': getattr(self, 'required', False),
+ }
+ optional_attrs = ['read_only', 'help_text', 'label',
+ 'min_length', 'max_length']
+ for attr in optional_attrs:
+ if getattr(self, attr, None) is not None:
+ humanized[attr] = getattr(self, attr)
+ return humanized
+
class WritableField(Field):
"""
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 943fba6b..072815df 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -521,6 +521,13 @@ class BaseSerializer(WritableField):
return self.object
+ @property
+ def humanized(self):
+ humanized_fields = SortedDict(
+ [(name, field.humanized)
+ for name, field in self.fields.iteritems()])
+ return humanized_fields
+
class Serializer(six.with_metaclass(SerializerMetaclass, BaseSerializer)):
pass
diff --git a/rest_framework/tests/fields.py b/rest_framework/tests/fields.py
index 85698092..fd1fe961 100644
--- a/rest_framework/tests/fields.py
+++ b/rest_framework/tests/fields.py
@@ -15,8 +15,7 @@ from django.test import TestCase
from django.utils.datastructures import SortedDict
from rest_framework import serializers
-from rest_framework.fields import (humanize_field, humanize_field_type,
- humanize_form_fields, Field)
+from rest_framework.fields import Field, CharField
from rest_framework.serializers import Serializer
from rest_framework.tests.models import RESTFrameworkModel
@@ -768,14 +767,16 @@ class SlugFieldTests(TestCase):
def test_given_serializer_value(self):
class SlugFieldSerializer(serializers.ModelSerializer):
- slug_field = serializers.SlugField(source='slug_field', max_length=20, required=False)
+ slug_field = serializers.SlugField(source='slug_field',
+ max_length=20, required=False)
class Meta:
model = self.SlugFieldModel
serializer = SlugFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
- self.assertEqual(getattr(serializer.fields['slug_field'], 'max_length'), 20)
+ self.assertEqual(getattr(serializer.fields['slug_field'],
+ 'max_length'), 20)
class URLFieldTests(TestCase):
@@ -796,7 +797,8 @@ class URLFieldTests(TestCase):
serializer = URLFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
- self.assertEqual(getattr(serializer.fields['url_field'], 'max_length'), 200)
+ self.assertEqual(getattr(serializer.fields['url_field'],
+ 'max_length'), 200)
def test_given_model_value(self):
class URLFieldSerializer(serializers.ModelSerializer):
@@ -805,48 +807,21 @@ class URLFieldTests(TestCase):
serializer = URLFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
- self.assertEqual(getattr(serializer.fields['url_field'], 'max_length'), 128)
+ self.assertEqual(getattr(serializer.fields['url_field'],
+ 'max_length'), 128)
def test_given_serializer_value(self):
class URLFieldSerializer(serializers.ModelSerializer):
- url_field = serializers.URLField(source='url_field', max_length=20, required=False)
+ url_field = serializers.URLField(source='url_field',
+ max_length=20, required=False)
class Meta:
model = self.URLFieldWithGivenMaxLengthModel
serializer = URLFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
- self.assertEqual(getattr(serializer.fields['url_field'], 'max_length'), 20)
-
-
-class HumanizedFieldType(TestCase):
- def test_standard_type_classes(self):
- for field_type_name in forms.fields.__all__:
- field_type = getattr(forms.fields, field_type_name)
- humanized = humanize_field_type(field_type)
- self.assert_valid_name(humanized)
-
- def test_standard_type_names(self):
- for field_type_name in forms.fields.__all__:
- humanized = humanize_field_type(field_type_name)
- self.assert_valid_name(humanized)
-
- def test_custom_type_name(self):
- humanized = humanize_field_type('SomeCustomType')
- self.assertEquals(humanized, u'Some custom type')
-
- def test_custom_type(self):
- custom_type = namedtuple('SomeCustomType', [])
- humanized = humanize_field_type(custom_type)
- self.assertEquals(humanized, u'Some custom type')
-
- def assert_valid_name(self, humanized):
- """A humanized field name is valid if it's a non-empty
- unicode.
-
- """
- self.assertIsInstance(humanized, unicode)
- self.assertNotEqual(humanized, '')
+ self.assertEqual(getattr(serializer.fields['url_field'],
+ 'max_length'), 20)
class HumanizedField(TestCase):
@@ -859,37 +834,41 @@ class HumanizedField(TestCase):
self.optional_field.label = uuid4().hex
self.optional_field.required = False
+ def test_type(self):
+ for field in (self.required_field, self.optional_field):
+ self.assertEqual(field.humanized['type'], field.type_name)
+
def test_required(self):
- self.assertEqual(humanize_field(self.required_field)['required'], True)
+ self.assertEqual(self.required_field.humanized['required'], True)
def test_optional(self):
- self.assertEqual(humanize_field(self.optional_field)['required'],
- False)
+ self.assertEqual(self.optional_field.humanized['required'], False)
def test_label(self):
for field in (self.required_field, self.optional_field):
- self.assertEqual(humanize_field(field)['label'], field.label)
+ self.assertEqual(field.humanized['label'], field.label)
-class Form(forms.Form):
- field1 = forms.CharField(max_length=3, label='field one')
- field2 = forms.CharField(label='field two')
+class HumanizableSerializer(Serializer):
+ field1 = CharField(3, required=True)
+ field2 = CharField(10, required=False)
class HumanizedSerializer(TestCase):
def setUp(self):
- self.serializer = TimestampedModelSerializer()
+ self.serializer = HumanizableSerializer()
def test_humanized(self):
- humanized = humanize_form_fields(Form())
+ humanized = self.serializer.humanized
expected = {
- 'field1': {u'help_text': u'',
- u'label': u'field one',
+ 'field1': {u'required': True,
u'max_length': 3,
- u'required': True,
- u'type': u'String'},
- 'field2': {u'help_text': u'',
- u'label': u'field two',
- u'required': True,
- u'type': u'String'}}
- self.assertEqual(humanized, expected)
+ u'type': u'CharField',
+ u'read_only': False},
+ 'field2': {u'required': False,
+ u'max_length': 10,
+ u'type': u'CharField',
+ u'read_only': False}}
+ self.assertEqual(set(expected.keys()), set(humanized.keys()))
+ for k, v in humanized.iteritems():
+ self.assertEqual(v, expected[k])
diff --git a/rest_framework/views.py b/rest_framework/views.py
index 5f9e1bf2..d1afbe89 100644
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -91,7 +91,7 @@ class APIView(View):
continue
serializer = self.get_serializer()
if serializer is not None:
- actions[method] = humanize_form_fields(serializer)
+ actions[method] = serializer.humanized
except exceptions.PermissionDenied:
# don't add this method
pass