First pass at pastebin tutorial

This commit is contained in:
Tom Christie 2012-10-18 23:48:52 +01:00
parent e8f542aac8
commit 643d3491a6
2 changed files with 82 additions and 11 deletions

View File

@ -7,6 +7,7 @@ from django.core import validators
from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.core.urlresolvers import resolve from django.core.urlresolvers import resolve
from django.conf import settings from django.conf import settings
from django.forms import widgets
from django.utils.encoding import is_protected_type, smart_unicode from django.utils.encoding import is_protected_type, smart_unicode
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from rest_framework.reverse import reverse from rest_framework.reverse import reverse
@ -105,10 +106,14 @@ class WritableField(Field):
'required': _('This field is required.'), 'required': _('This field is required.'),
'invalid': _('Invalid value.'), 'invalid': _('Invalid value.'),
} }
widget = widgets.TextInput
def __init__(self, source=None, readonly=False, required=None, def __init__(self, source=None, readonly=False, required=None,
validators=[], error_messages=None): validators=[], error_messages=None, widget=None,
help_text=None, initial=None):
super(WritableField, self).__init__(source=source) super(WritableField, self).__init__(source=source)
self.readonly = readonly self.readonly = readonly
if required is None: if required is None:
self.required = not(readonly) self.required = not(readonly)
@ -124,6 +129,15 @@ class WritableField(Field):
self.validators = self.default_validators + validators self.validators = self.default_validators + validators
# These attributes are ony used for HTML forms.
self.initial = initial
self.help_text = help_text and smart_unicode(help_text) or ''
widget = widget or self.widget
if isinstance(widget, type):
widget = widget()
self.widget = widget
def validate(self, value): def validate(self, value):
if value in validators.EMPTY_VALUES and self.required: if value in validators.EMPTY_VALUES and self.required:
raise ValidationError(self.error_messages['required']) raise ValidationError(self.error_messages['required'])
@ -157,9 +171,12 @@ class WritableField(Field):
try: try:
native = data[field_name] native = data[field_name]
except KeyError: except KeyError:
if self.required: if getattr(self, 'missing_value', None) is not None:
raise ValidationError(self.error_messages['required']) native = self.missing_value
return else:
if self.required:
raise ValidationError(self.error_messages['required'])
return
value = self.from_native(native) value = self.from_native(native)
if self.source == '*': if self.source == '*':
@ -394,20 +411,19 @@ class HyperlinkedIdentityField(Field):
class BooleanField(WritableField): class BooleanField(WritableField):
type_name = 'BooleanField' type_name = 'BooleanField'
widget = widgets.CheckboxInput
default_error_messages = { default_error_messages = {
'invalid': _(u"'%s' value must be either True or False."), 'invalid': _(u"'%s' value must be either True or False."),
} }
empty = False
missing_value = False # Fill in missing value not supplied by html form
def from_native(self, value): def from_native(self, value):
if value in (True, False):
# if value is 1 or 0 than it's equal to True or False, but we want
# to return a true bool for semantic reasons.
return bool(value)
if value in ('t', 'True', '1'): if value in ('t', 'True', '1'):
return True return True
if value in ('f', 'False', '0'): if value in ('f', 'False', '0'):
return False return False
raise ValidationError(self.error_messages['invalid'] % value) return bool(value)
class CharField(WritableField): class CharField(WritableField):
@ -427,6 +443,52 @@ class CharField(WritableField):
return smart_unicode(value) return smart_unicode(value)
class ChoiceField(WritableField):
type_name = 'ChoiceField'
widget = widgets.Select
default_error_messages = {
'invalid_choice': _('Select a valid choice. %(value)s is not one of the available choices.'),
}
def __init__(self, choices=(), *args, **kwargs):
super(ChoiceField, self).__init__(*args, **kwargs)
self.choices = choices
def _get_choices(self):
return self._choices
def _set_choices(self, value):
# Setting choices also sets the choices on the widget.
# choices can be any iterable, but we call list() on it because
# it will be consumed more than once.
self._choices = self.widget.choices = list(value)
choices = property(_get_choices, _set_choices)
def validate(self, value):
"""
Validates that the input is in self.choices.
"""
super(ChoiceField, self).validate(value)
if value and not self.valid_value(value):
raise ValidationError(self.error_messages['invalid_choice'] % {'value': value})
def valid_value(self, value):
"""
Check to see if the provided value is a valid choice.
"""
for k, v in self.choices:
if isinstance(v, (list, tuple)):
# This is an optgroup, so look inside the group for options
for k2, v2 in v:
if value == smart_unicode(k2):
return True
else:
if value == smart_unicode(k):
return True
return False
class EmailField(CharField): class EmailField(CharField):
type_name = 'EmailField' type_name = 'EmailField'

View File

@ -279,13 +279,22 @@ class BrowsableAPIRenderer(BaseRenderer):
continue continue
kwargs = {} kwargs = {}
kwargs['required'] = v.required
if getattr(v, 'queryset', None): if getattr(v, 'queryset', None):
kwargs['queryset'] = getattr(v, 'queryset', None) kwargs['queryset'] = v.queryset
if getattr(v, 'widget', None):
kwargs['widget'] = v.widget
if getattr(v, 'initial', None):
kwargs['initial'] = v.initial
if getattr(v, 'help_text', None):
kwargs['help_text'] = v.help_text
kwargs['label'] = k
print kwargs
try: try:
fields[k] = field_mapping[v.__class__](**kwargs) fields[k] = field_mapping[v.__class__](**kwargs)
except KeyError: except KeyError:
fields[k] = forms.CharField() fields[k] = forms.CharField(**kwargs)
OnTheFlyForm = type("OnTheFlyForm", (forms.Form,), fields) OnTheFlyForm = type("OnTheFlyForm", (forms.Form,), fields)
if obj and not view.request.method == 'DELETE': # Don't fill in the form when the object is deleted if obj and not view.request.method == 'DELETE': # Don't fill in the form when the object is deleted