diff --git a/rest_framework/fields.py b/rest_framework/fields.py index c83ee5ecf..3c4e975ae 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -108,7 +108,7 @@ class Field(object): use_files = False form_field_class = forms.CharField - def __init__(self, source=None): + def __init__(self, source=None, label=None, help_text=None): self.parent = None self.creation_counter = Field.creation_counter @@ -116,6 +116,12 @@ class Field(object): self.source = source + if label is not None: + self.label = smart_unicode(label) + + if help_text is not None: + self.help_text = smart_unicode(help_text) + def initialize(self, parent, field_name): """ Called to set up a field prior to field_to_native or field_from_native. @@ -194,7 +200,8 @@ class WritableField(Field): widget = widgets.TextInput default = None - def __init__(self, source=None, read_only=False, required=None, + def __init__(self, source=None, label=None, help_text=None, + read_only=False, required=None, validators=[], error_messages=None, widget=None, default=None, blank=None): @@ -205,7 +212,7 @@ class WritableField(Field): DeprecationWarning, stacklevel=2) required = not(blank) - super(WritableField, self).__init__(source=source) + super(WritableField, self).__init__(source=source, label=label, help_text=help_text) self.read_only = read_only if required is None: diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 7707de7a7..942ab3994 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -724,6 +724,12 @@ class ModelSerializer(Serializer): kwargs['choices'] = model_field.flatchoices return ChoiceField(**kwargs) + if model_field.verbose_name is not None: + kwargs['label'] = model_field.verbose_name + + if model_field.help_text is not None: + kwargs['help_text'] = model_field.help_text + try: return self.field_mapping[model_field.__class__](**kwargs) except KeyError: diff --git a/rest_framework/tests/models.py b/rest_framework/tests/models.py index 40e41a644..3465268b6 100644 --- a/rest_framework/tests/models.py +++ b/rest_framework/tests/models.py @@ -1,5 +1,6 @@ from __future__ import unicode_literals from django.db import models +from django.utils.translation import ugettext_lazy as _ def foobar(): @@ -32,7 +33,7 @@ class Anchor(RESTFrameworkModel): class BasicModel(RESTFrameworkModel): - text = models.CharField(max_length=100) + text = models.CharField(max_length=100, verbose_name=_("Text"), help_text=_("Text description.")) class SlugBasedModel(RESTFrameworkModel): diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py index db3881f9a..b0c7e5689 100644 --- a/rest_framework/tests/serializer.py +++ b/rest_framework/tests/serializer.py @@ -1,7 +1,7 @@ from __future__ import unicode_literals from django.utils.datastructures import MultiValueDict from django.test import TestCase -from rest_framework import serializers +from rest_framework import serializers, fields from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel, BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel, ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo) @@ -1143,3 +1143,32 @@ class DeserializeListTestCase(TestCase): self.assertFalse(serializer.is_valid()) expected = [{}, {'email': ['This field is required.']}, {}] self.assertEqual(serializer.errors, expected) + + +# Test for issue #467 +class FieldLabelTest(TestCase): + def setUp(self): + class LabelModelSerializer(serializers.ModelSerializer): + class Meta: + model = BasicModel + + self.serializer_class = LabelModelSerializer + + def test_label_from_model(self): + """ + Validates that label and help_text are correctly copied from the model class. + """ + serializer = self.serializer_class() + text_field = serializer.fields['text'] + + self.assertEquals(u'Text', text_field.label) + self.assertEquals(u'Text description.', text_field.help_text) + + def test_field_ctor(self): + """ + This is check that ctor supports both label and help_text. + """ + self.assertEquals(u'Label', fields.Field(label='Label', help_text='Help').label) + self.assertEquals(u'Help', fields.CharField(label='Label', help_text='Help').help_text) + self.assertEquals(u'Label', fields.ManyHyperlinkedRelatedField(view_name='fake', label='Label', help_text='Help').label) +