diff options
Diffstat (limited to 'rest_framework/fields.py')
| -rw-r--r-- | rest_framework/fields.py | 29 |
1 files changed, 23 insertions, 6 deletions
diff --git a/rest_framework/fields.py b/rest_framework/fields.py index e23fc001..2f475d6e 100644 --- a/rest_framework/fields.py +++ b/rest_framework/fields.py @@ -246,6 +246,7 @@ class WritableField(Field): """ Base for read/write fields. """ + write_only = False default_validators = [] default_error_messages = { 'required': _('This field is required.'), @@ -255,7 +256,7 @@ class WritableField(Field): default = None def __init__(self, source=None, label=None, help_text=None, - read_only=False, required=None, + read_only=False, write_only=False, required=None, validators=[], error_messages=None, widget=None, default=None, blank=None): @@ -269,6 +270,10 @@ class WritableField(Field): super(WritableField, self).__init__(source=source, label=label, help_text=help_text) self.read_only = read_only + self.write_only = write_only + + assert not (read_only and write_only), "Cannot set read_only=True and write_only=True" + if required is None: self.required = not(read_only) else: @@ -318,6 +323,11 @@ class WritableField(Field): if errors: raise ValidationError(errors) + def field_to_native(self, obj, field_name): + if self.write_only: + return None + return super(WritableField, self).field_to_native(obj, field_name) + def field_from_native(self, data, files, field_name, into): """ Given a dictionary and a field name, updates the dictionary `into`, @@ -428,7 +438,7 @@ class BooleanField(WritableField): def field_from_native(self, data, files, field_name, into): # HTML checkboxes do not explicitly represent unchecked as `False` # we deal with that here... - if isinstance(data, QueryDict): + if isinstance(data, QueryDict) and self.default is None: self.default = False return super(BooleanField, self).field_from_native( @@ -497,6 +507,7 @@ class ChoiceField(WritableField): } def __init__(self, choices=(), *args, **kwargs): + self.empty = kwargs.pop('empty', '') super(ChoiceField, self).__init__(*args, **kwargs) self.choices = choices if not self.required: @@ -513,6 +524,11 @@ class ChoiceField(WritableField): choices = property(_get_choices, _set_choices) + def metadata(self): + data = super(ChoiceField, self).metadata() + data['choices'] = [{'value': v, 'display_name': n} for v, n in self.choices] + return data + def validate(self, value): """ Validates that the input is in self.choices. @@ -537,9 +553,10 @@ class ChoiceField(WritableField): return False def from_native(self, value): - if value in validators.EMPTY_VALUES: - return None - return super(ChoiceField, self).from_native(value) + value = super(ChoiceField, self).from_native(value) + if value == self.empty or value in validators.EMPTY_VALUES: + return self.empty + return value class EmailField(CharField): @@ -964,7 +981,7 @@ class ImageField(FileField): return None from rest_framework.compat import Image - assert Image is not None, 'PIL must be installed for ImageField support' + assert Image is not None, 'Either Pillow or PIL must be installed for ImageField support.' # We need to get a file object for PIL. We might have a path or we might # have to read the data into memory. |
