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
|
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
|
# Django-guardian is optional. Import only if guardian is in INSTALLED_APPS
|
||||||
# Fixes (#1712). We keep the try/except for the test suite.
|
# Fixes (#1712). We keep the try/except for the test suite.
|
||||||
guardian = None
|
guardian = None
|
||||||
|
@ -99,18 +110,8 @@ def get_concrete_model(model_cls):
|
||||||
return 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
|
# PATCH method is not implemented by Django
|
||||||
|
from django.views.generic import View
|
||||||
if 'patch' not in View.http_method_names:
|
if 'patch' not in View.http_method_names:
|
||||||
View.http_method_names = View.http_method_names + ['patch']
|
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,
|
def __init__(self, read_only=False, write_only=False,
|
||||||
required=None, default=empty, initial=None, source=None,
|
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
|
self._creation_counter = Field._creation_counter
|
||||||
Field._creation_counter += 1
|
Field._creation_counter += 1
|
||||||
|
|
||||||
|
@ -122,6 +123,7 @@ class Field(object):
|
||||||
self.source = source
|
self.source = source
|
||||||
self.initial = initial
|
self.initial = initial
|
||||||
self.label = label
|
self.label = label
|
||||||
|
self.help_text = help_text
|
||||||
self.style = {} if style is None else style
|
self.style = {} if style is None else style
|
||||||
self.validators = validators or self.default_validators[:]
|
self.validators = validators or self.default_validators[:]
|
||||||
|
|
||||||
|
@ -372,7 +374,6 @@ class IntegerField(Field):
|
||||||
self.validators.append(validators.MaxValueValidator(max_value))
|
self.validators.append(validators.MaxValueValidator(max_value))
|
||||||
if min_value is not None:
|
if min_value is not None:
|
||||||
self.validators.append(validators.MinValueValidator(min_value))
|
self.validators.append(validators.MinValueValidator(min_value))
|
||||||
print self.__class__.__name__, self.validators
|
|
||||||
|
|
||||||
def to_native(self, data):
|
def to_native(self, data):
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -15,6 +15,7 @@ from django.core.exceptions import ValidationError
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from collections import namedtuple, OrderedDict
|
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.fields import empty, set_value, Field, SkipField
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
from rest_framework.utils import html, modelinfo, representation
|
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.
|
This metaclass sets a dictionary named `base_fields` on the class.
|
||||||
|
|
||||||
Any fields included as attributes on either the class or it's superclasses
|
Any instances of `Field` included as attributes on either the class
|
||||||
will be include in the `base_fields` dictionary.
|
or on any of its superclasses will be include in the
|
||||||
|
`base_fields` dictionary.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
@ -379,6 +381,10 @@ class ModelSerializer(Serializer):
|
||||||
info = modelinfo.get_field_info(self.opts.model)
|
info = modelinfo.get_field_info(self.opts.model)
|
||||||
ret = OrderedDict()
|
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)
|
serializer_pk_field = self.get_pk_field(info.pk)
|
||||||
if serializer_pk_field:
|
if serializer_pk_field:
|
||||||
ret[info.pk.name] = serializer_pk_field
|
ret[info.pk.name] = serializer_pk_field
|
||||||
|
@ -404,6 +410,9 @@ class ModelSerializer(Serializer):
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
def get_url_field(self):
|
||||||
|
return None
|
||||||
|
|
||||||
def get_pk_field(self, model_field):
|
def get_pk_field(self, model_field):
|
||||||
"""
|
"""
|
||||||
Returns a default instance of the pk field.
|
Returns a default instance of the pk field.
|
||||||
|
@ -446,13 +455,14 @@ class ModelSerializer(Serializer):
|
||||||
if model_field:
|
if model_field:
|
||||||
if model_field.null or model_field.blank:
|
if model_field.null or model_field.blank:
|
||||||
kwargs['required'] = False
|
kwargs['required'] = False
|
||||||
# if model_field.help_text is not None:
|
if model_field.verbose_name:
|
||||||
# kwargs['help_text'] = model_field.help_text
|
|
||||||
if model_field.verbose_name is not None:
|
|
||||||
kwargs['label'] = model_field.verbose_name
|
kwargs['label'] = model_field.verbose_name
|
||||||
if not model_field.editable:
|
if not model_field.editable:
|
||||||
kwargs['read_only'] = True
|
kwargs['read_only'] = True
|
||||||
kwargs.pop('queryset', None)
|
kwargs.pop('queryset', None)
|
||||||
|
help_text = clean_manytomany_helptext(model_field.help_text)
|
||||||
|
if help_text:
|
||||||
|
kwargs['help_text'] = help_text
|
||||||
|
|
||||||
return PrimaryKeyRelatedField(**kwargs)
|
return PrimaryKeyRelatedField(**kwargs)
|
||||||
|
|
||||||
|
@ -469,6 +479,9 @@ class ModelSerializer(Serializer):
|
||||||
if model_field.verbose_name is not None:
|
if model_field.verbose_name is not None:
|
||||||
kwargs['label'] = model_field.verbose_name
|
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:
|
if isinstance(model_field, models.AutoField) or not model_field.editable:
|
||||||
kwargs['read_only'] = True
|
kwargs['read_only'] = True
|
||||||
# Read only implies that the field is not required.
|
# 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.
|
# We have a cleaner repr on the instance if we don't set it.
|
||||||
kwargs.pop('required', None)
|
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,
|
# Ensure that max_length is passed explicitly as a keyword arg,
|
||||||
# rather than as a validator.
|
# rather than as a validator.
|
||||||
max_length = getattr(model_field, 'max_length', None)
|
max_length = getattr(model_field, 'max_length', None)
|
||||||
|
@ -561,23 +582,6 @@ class ModelSerializer(Serializer):
|
||||||
if validator_kwarg:
|
if validator_kwarg:
|
||||||
kwargs['validators'] = 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:
|
try:
|
||||||
return self.field_mapping[model_field.__class__](**kwargs)
|
return self.field_mapping[model_field.__class__](**kwargs)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
|
@ -597,33 +601,24 @@ class HyperlinkedModelSerializerOptions(ModelSerializerOptions):
|
||||||
class HyperlinkedModelSerializer(ModelSerializer):
|
class HyperlinkedModelSerializer(ModelSerializer):
|
||||||
_options_class = HyperlinkedModelSerializerOptions
|
_options_class = HyperlinkedModelSerializerOptions
|
||||||
|
|
||||||
def get_default_fields(self):
|
def get_url_field(self):
|
||||||
fields = super(HyperlinkedModelSerializer, self).get_default_fields()
|
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:
|
kwargs = {
|
||||||
self.opts.view_name = self.get_default_view_name(self.opts.model)
|
'view_name': view_name
|
||||||
|
}
|
||||||
|
if self.opts.lookup_field:
|
||||||
|
kwargs['lookup_field'] = self.opts.lookup_field
|
||||||
|
|
||||||
url_field_name = api_settings.URL_FIELD_NAME
|
return HyperlinkedIdentityField(**kwargs)
|
||||||
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
|
|
||||||
|
|
||||||
def get_pk_field(self, model_field):
|
def get_pk_field(self, model_field):
|
||||||
if self.opts.fields and model_field.name in self.opts.fields:
|
if self.opts.fields and model_field.name in self.opts.fields:
|
||||||
return self.get_field(model_field)
|
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):
|
def get_related_field(self, model_field, related_model, to_many, has_through_model):
|
||||||
"""
|
"""
|
||||||
Creates a default instance of a flat relational field.
|
Creates a default instance of a flat relational field.
|
||||||
|
@ -643,13 +638,14 @@ class HyperlinkedModelSerializer(ModelSerializer):
|
||||||
if model_field:
|
if model_field:
|
||||||
if model_field.null or model_field.blank:
|
if model_field.null or model_field.blank:
|
||||||
kwargs['required'] = False
|
kwargs['required'] = False
|
||||||
# if model_field.help_text is not None:
|
if model_field.verbose_name:
|
||||||
# kwargs['help_text'] = model_field.help_text
|
|
||||||
if model_field.verbose_name is not None:
|
|
||||||
kwargs['label'] = model_field.verbose_name
|
kwargs['label'] = model_field.verbose_name
|
||||||
if not model_field.editable:
|
if not model_field.editable:
|
||||||
kwargs['read_only'] = True
|
kwargs['read_only'] = True
|
||||||
kwargs.pop('queryset', None)
|
kwargs.pop('queryset', None)
|
||||||
|
help_text = clean_manytomany_helptext(model_field.help_text)
|
||||||
|
if help_text:
|
||||||
|
kwargs['help_text'] = help_text
|
||||||
|
|
||||||
return HyperlinkedRelatedField(**kwargs)
|
return HyperlinkedRelatedField(**kwargs)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user