mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-02-02 20:54:42 +03:00
Added help_text argument to fields
This commit is contained in:
parent
234369aefd
commit
01c8c0cad9
|
@ -39,6 +39,17 @@ except ImportError:
|
|||
django_filters = None
|
||||
|
||||
|
||||
if django.VERSION >= (1, 6):
|
||||
def clean_manytomany_helptext(text):
|
||||
return text
|
||||
else:
|
||||
# Up to version 1.5 many to many fields automatically suffix
|
||||
# the `help_text` attribute with hardcoded text.
|
||||
def clean_manytomany_helptext(text):
|
||||
if text.endswith(' Hold down "Control", or "Command" on a Mac, to select more than one.'):
|
||||
text = text[:-69]
|
||||
return text
|
||||
|
||||
# Django-guardian is optional. Import only if guardian is in INSTALLED_APPS
|
||||
# Fixes (#1712). We keep the try/except for the test suite.
|
||||
guardian = None
|
||||
|
@ -99,18 +110,8 @@ def get_concrete_model(model_cls):
|
|||
return model_cls
|
||||
|
||||
|
||||
# View._allowed_methods only present from 1.5 onwards
|
||||
if django.VERSION >= (1, 5):
|
||||
from django.views.generic import View
|
||||
else:
|
||||
from django.views.generic import View as DjangoView
|
||||
|
||||
class View(DjangoView):
|
||||
def _allowed_methods(self):
|
||||
return [m.upper() for m in self.http_method_names if hasattr(self, m)]
|
||||
|
||||
|
||||
# PATCH method is not implemented by Django
|
||||
from django.views.generic import View
|
||||
if 'patch' not in View.http_method_names:
|
||||
View.http_method_names = View.http_method_names + ['patch']
|
||||
|
||||
|
|
|
@ -101,7 +101,8 @@ class Field(object):
|
|||
|
||||
def __init__(self, read_only=False, write_only=False,
|
||||
required=None, default=empty, initial=None, source=None,
|
||||
label=None, style=None, error_messages=None, validators=[]):
|
||||
label=None, help_text=None, style=None,
|
||||
error_messages=None, validators=[]):
|
||||
self._creation_counter = Field._creation_counter
|
||||
Field._creation_counter += 1
|
||||
|
||||
|
@ -122,6 +123,7 @@ class Field(object):
|
|||
self.source = source
|
||||
self.initial = initial
|
||||
self.label = label
|
||||
self.help_text = help_text
|
||||
self.style = {} if style is None else style
|
||||
self.validators = validators or self.default_validators[:]
|
||||
|
||||
|
@ -372,7 +374,6 @@ class IntegerField(Field):
|
|||
self.validators.append(validators.MaxValueValidator(max_value))
|
||||
if min_value is not None:
|
||||
self.validators.append(validators.MinValueValidator(min_value))
|
||||
print self.__class__.__name__, self.validators
|
||||
|
||||
def to_native(self, data):
|
||||
try:
|
||||
|
|
|
@ -15,6 +15,7 @@ from django.core.exceptions import ValidationError
|
|||
from django.db import models
|
||||
from django.utils import six
|
||||
from collections import namedtuple, OrderedDict
|
||||
from rest_framework.compat import clean_manytomany_helptext
|
||||
from rest_framework.fields import empty, set_value, Field, SkipField
|
||||
from rest_framework.settings import api_settings
|
||||
from rest_framework.utils import html, modelinfo, representation
|
||||
|
@ -117,8 +118,9 @@ class SerializerMetaclass(type):
|
|||
"""
|
||||
This metaclass sets a dictionary named `base_fields` on the class.
|
||||
|
||||
Any fields included as attributes on either the class or it's superclasses
|
||||
will be include in the `base_fields` dictionary.
|
||||
Any instances of `Field` included as attributes on either the class
|
||||
or on any of its superclasses will be include in the
|
||||
`base_fields` dictionary.
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
|
@ -379,6 +381,10 @@ class ModelSerializer(Serializer):
|
|||
info = modelinfo.get_field_info(self.opts.model)
|
||||
ret = OrderedDict()
|
||||
|
||||
serializer_url_field = self.get_url_field()
|
||||
if serializer_url_field:
|
||||
ret[api_settings.URL_FIELD_NAME] = serializer_url_field
|
||||
|
||||
serializer_pk_field = self.get_pk_field(info.pk)
|
||||
if serializer_pk_field:
|
||||
ret[info.pk.name] = serializer_pk_field
|
||||
|
@ -404,6 +410,9 @@ class ModelSerializer(Serializer):
|
|||
|
||||
return ret
|
||||
|
||||
def get_url_field(self):
|
||||
return None
|
||||
|
||||
def get_pk_field(self, model_field):
|
||||
"""
|
||||
Returns a default instance of the pk field.
|
||||
|
@ -446,13 +455,14 @@ class ModelSerializer(Serializer):
|
|||
if model_field:
|
||||
if model_field.null or model_field.blank:
|
||||
kwargs['required'] = False
|
||||
# if model_field.help_text is not None:
|
||||
# kwargs['help_text'] = model_field.help_text
|
||||
if model_field.verbose_name is not None:
|
||||
if model_field.verbose_name:
|
||||
kwargs['label'] = model_field.verbose_name
|
||||
if not model_field.editable:
|
||||
kwargs['read_only'] = True
|
||||
kwargs.pop('queryset', None)
|
||||
help_text = clean_manytomany_helptext(model_field.help_text)
|
||||
if help_text:
|
||||
kwargs['help_text'] = help_text
|
||||
|
||||
return PrimaryKeyRelatedField(**kwargs)
|
||||
|
||||
|
@ -469,6 +479,9 @@ class ModelSerializer(Serializer):
|
|||
if model_field.verbose_name is not None:
|
||||
kwargs['label'] = model_field.verbose_name
|
||||
|
||||
if model_field.help_text:
|
||||
kwargs['help_text'] = model_field.help_text
|
||||
|
||||
if isinstance(model_field, models.AutoField) or not model_field.editable:
|
||||
kwargs['read_only'] = True
|
||||
# Read only implies that the field is not required.
|
||||
|
@ -481,6 +494,14 @@ class ModelSerializer(Serializer):
|
|||
# We have a cleaner repr on the instance if we don't set it.
|
||||
kwargs.pop('required', None)
|
||||
|
||||
if model_field.flatchoices:
|
||||
# If this model field contains choices, then use a ChoiceField,
|
||||
# rather than the standard serializer field for this type.
|
||||
# Note that we return this prior to setting any validation type
|
||||
# keyword arguments, as those are not valid initializers.
|
||||
kwargs['choices'] = model_field.flatchoices
|
||||
return ChoiceField(**kwargs)
|
||||
|
||||
# Ensure that max_length is passed explicitly as a keyword arg,
|
||||
# rather than as a validator.
|
||||
max_length = getattr(model_field, 'max_length', None)
|
||||
|
@ -561,23 +582,6 @@ class ModelSerializer(Serializer):
|
|||
if validator_kwarg:
|
||||
kwargs['validators'] = validator_kwarg
|
||||
|
||||
# if issubclass(model_field.__class__, models.TextField):
|
||||
# kwargs['widget'] = widgets.Textarea
|
||||
|
||||
# if model_field.help_text is not None:
|
||||
# kwargs['help_text'] = model_field.help_text
|
||||
|
||||
# TODO: TypedChoiceField?
|
||||
if model_field.flatchoices: # This ModelField contains choices
|
||||
kwargs['choices'] = model_field.flatchoices
|
||||
if model_field.null:
|
||||
kwargs['empty'] = None
|
||||
return ChoiceField(**kwargs)
|
||||
|
||||
if model_field.null and \
|
||||
issubclass(model_field.__class__, (models.CharField, models.TextField)):
|
||||
kwargs['allow_none'] = True
|
||||
|
||||
try:
|
||||
return self.field_mapping[model_field.__class__](**kwargs)
|
||||
except KeyError:
|
||||
|
@ -597,33 +601,24 @@ class HyperlinkedModelSerializerOptions(ModelSerializerOptions):
|
|||
class HyperlinkedModelSerializer(ModelSerializer):
|
||||
_options_class = HyperlinkedModelSerializerOptions
|
||||
|
||||
def get_default_fields(self):
|
||||
fields = super(HyperlinkedModelSerializer, self).get_default_fields()
|
||||
def get_url_field(self):
|
||||
if self.opts.view_name is not None:
|
||||
view_name = self.opts.view_name
|
||||
else:
|
||||
view_name = self.get_default_view_name(self.opts.model)
|
||||
|
||||
if self.opts.view_name is None:
|
||||
self.opts.view_name = self.get_default_view_name(self.opts.model)
|
||||
kwargs = {
|
||||
'view_name': view_name
|
||||
}
|
||||
if self.opts.lookup_field:
|
||||
kwargs['lookup_field'] = self.opts.lookup_field
|
||||
|
||||
url_field_name = api_settings.URL_FIELD_NAME
|
||||
if url_field_name not in fields:
|
||||
ret = fields.__class__()
|
||||
ret[url_field_name] = self.get_url_field()
|
||||
ret.update(fields)
|
||||
fields = ret
|
||||
|
||||
return fields
|
||||
return HyperlinkedIdentityField(**kwargs)
|
||||
|
||||
def get_pk_field(self, model_field):
|
||||
if self.opts.fields and model_field.name in self.opts.fields:
|
||||
return self.get_field(model_field)
|
||||
|
||||
def get_url_field(self):
|
||||
kwargs = {
|
||||
'view_name': self.get_default_view_name(self.opts.model)
|
||||
}
|
||||
if self.opts.lookup_field:
|
||||
kwargs['lookup_field'] = self.opts.lookup_field
|
||||
return HyperlinkedIdentityField(**kwargs)
|
||||
|
||||
def get_related_field(self, model_field, related_model, to_many, has_through_model):
|
||||
"""
|
||||
Creates a default instance of a flat relational field.
|
||||
|
@ -643,13 +638,14 @@ class HyperlinkedModelSerializer(ModelSerializer):
|
|||
if model_field:
|
||||
if model_field.null or model_field.blank:
|
||||
kwargs['required'] = False
|
||||
# if model_field.help_text is not None:
|
||||
# kwargs['help_text'] = model_field.help_text
|
||||
if model_field.verbose_name is not None:
|
||||
if model_field.verbose_name:
|
||||
kwargs['label'] = model_field.verbose_name
|
||||
if not model_field.editable:
|
||||
kwargs['read_only'] = True
|
||||
kwargs.pop('queryset', None)
|
||||
help_text = clean_manytomany_helptext(model_field.help_text)
|
||||
if help_text:
|
||||
kwargs['help_text'] = help_text
|
||||
|
||||
return HyperlinkedRelatedField(**kwargs)
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user