diff options
Diffstat (limited to 'django/oldforms/__init__.py')
| -rw-r--r-- | django/oldforms/__init__.py | 1056 |
1 files changed, 0 insertions, 1056 deletions
diff --git a/django/oldforms/__init__.py b/django/oldforms/__init__.py deleted file mode 100644 index b5698ab807..0000000000 --- a/django/oldforms/__init__.py +++ /dev/null @@ -1,1056 +0,0 @@ -from django.core import validators -from django.core.exceptions import PermissionDenied -from django.utils.html import escape -from django.utils.safestring import mark_safe -from django.conf import settings -from django.utils.translation import ugettext, ungettext -from django.utils.encoding import smart_unicode, force_unicode - -FORM_FIELD_ID_PREFIX = 'id_' - -class EmptyValue(Exception): - "This is raised when empty data is provided" - pass - -class Manipulator(object): - # List of permission strings. User must have at least one to manipulate. - # None means everybody has permission. - required_permission = '' - - def __init__(self): - # List of FormField objects - self.fields = [] - - def __getitem__(self, field_name): - "Looks up field by field name; raises KeyError on failure" - for field in self.fields: - if field.field_name == field_name: - return field - raise KeyError, "Field %s not found\n%s" % (field_name, repr(self.fields)) - - def __delitem__(self, field_name): - "Deletes the field with the given field name; raises KeyError on failure" - for i, field in enumerate(self.fields): - if field.field_name == field_name: - del self.fields[i] - return - raise KeyError, "Field %s not found" % field_name - - def check_permissions(self, user): - """Confirms user has required permissions to use this manipulator; raises - PermissionDenied on failure.""" - if self.required_permission is None: - return - if user.has_perm(self.required_permission): - return - raise PermissionDenied - - def prepare(self, new_data): - """ - Makes any necessary preparations to new_data, in place, before data has - been validated. - """ - for field in self.fields: - field.prepare(new_data) - - def get_validation_errors(self, new_data): - "Returns dictionary mapping field_names to error-message lists" - errors = {} - self.prepare(new_data) - for field in self.fields: - errors.update(field.get_validation_errors(new_data)) - val_name = 'validate_%s' % field.field_name - if hasattr(self, val_name): - val = getattr(self, val_name) - try: - field.run_validator(new_data, val) - except (validators.ValidationError, validators.CriticalValidationError), e: - errors.setdefault(field.field_name, []).extend(e.messages) - -# if field.is_required and not new_data.get(field.field_name, False): -# errors.setdefault(field.field_name, []).append(ugettext_lazy('This field is required.')) -# continue -# try: -# validator_list = field.validator_list -# if hasattr(self, 'validate_%s' % field.field_name): -# validator_list.append(getattr(self, 'validate_%s' % field.field_name)) -# for validator in validator_list: -# if field.is_required or new_data.get(field.field_name, False) or hasattr(validator, 'always_test'): -# try: -# if hasattr(field, 'requires_data_list'): -# validator(new_data.getlist(field.field_name), new_data) -# else: -# validator(new_data.get(field.field_name, ''), new_data) -# except validators.ValidationError, e: -# errors.setdefault(field.field_name, []).extend(e.messages) -# # If a CriticalValidationError is raised, ignore any other ValidationErrors -# # for this particular field -# except validators.CriticalValidationError, e: -# errors.setdefault(field.field_name, []).extend(e.messages) - return errors - - def save(self, new_data): - "Saves the changes and returns the new object" - # changes is a dictionary-like object keyed by field_name - raise NotImplementedError - - def do_html2python(self, new_data): - """ - Convert the data from HTML data types to Python datatypes, changing the - object in place. This happens after validation but before storage. This - must happen after validation because html2python functions aren't - expected to deal with invalid input. - """ - for field in self.fields: - field.convert_post_data(new_data) - -class FormWrapper(object): - """ - A wrapper linking a Manipulator to the template system. - This allows dictionary-style lookups of formfields. It also handles feeding - prepopulated data and validation error messages to the formfield objects. - """ - def __init__(self, manipulator, data=None, error_dict=None, edit_inline=True): - self.manipulator = manipulator - if data is None: - data = {} - if error_dict is None: - error_dict = {} - self.data = data - self.error_dict = error_dict - self._inline_collections = None - self.edit_inline = edit_inline - - def __repr__(self): - return repr(self.__dict__) - - def __getitem__(self, key): - for field in self.manipulator.fields: - if field.field_name == key: - data = field.extract_data(self.data) - return FormFieldWrapper(field, data, self.error_dict.get(field.field_name, [])) - if self.edit_inline: - self.fill_inline_collections() - for inline_collection in self._inline_collections: - # The 'orig_name' comparison is for backwards compatibility - # with hand-crafted forms. - if inline_collection.name == key or (':' not in key and inline_collection.orig_name == key): - return inline_collection - raise KeyError, "Could not find Formfield or InlineObjectCollection named %r" % key - - def fill_inline_collections(self): - if not self._inline_collections: - ic = [] - related_objects = self.manipulator.get_related_objects() - for rel_obj in related_objects: - data = rel_obj.extract_data(self.data) - inline_collection = InlineObjectCollection(self.manipulator, rel_obj, data, self.error_dict) - ic.append(inline_collection) - self._inline_collections = ic - - def has_errors(self): - return self.error_dict != {} - - def _get_fields(self): - try: - return self._fields - except AttributeError: - self._fields = [self.__getitem__(field.field_name) for field in self.manipulator.fields] - return self._fields - - fields = property(_get_fields) - -class FormFieldWrapper(object): - "A bridge between the template system and an individual form field. Used by FormWrapper." - def __init__(self, formfield, data, error_list): - self.formfield, self.data, self.error_list = formfield, data, error_list - self.field_name = self.formfield.field_name # for convenience in templates - - def __str__(self): - "Renders the field" - return unicode(self).encode('utf-8') - - def __unicode__(self): - "Renders the field" - return force_unicode(self.formfield.render(self.data)) - - def __repr__(self): - return '<FormFieldWrapper for "%s">' % self.formfield.field_name - - def field_list(self): - """ - Like __str__(), but returns a list. Use this when the field's render() - method returns a list. - """ - return self.formfield.render(self.data) - - def errors(self): - return self.error_list - - def html_error_list(self): - if self.errors(): - return mark_safe('<ul class="errorlist"><li>%s</li></ul>' % '</li><li>'.join([escape(e) for e in self.errors()])) - else: - return mark_safe('') - - def get_id(self): - return self.formfield.get_id() - -class FormFieldCollection(FormFieldWrapper): - "A utility class that gives the template access to a dict of FormFieldWrappers" - def __init__(self, formfield_dict): - self.formfield_dict = formfield_dict - - def __str__(self): - return unicode(self).encode('utf-8') - - def __unicode__(self): - return unicode(self.formfield_dict) - - def __getitem__(self, template_key): - "Look up field by template key; raise KeyError on failure" - return self.formfield_dict[template_key] - - def __repr__(self): - return "<FormFieldCollection: %s>" % self.formfield_dict - - def errors(self): - "Returns list of all errors in this collection's formfields" - errors = [] - for field in self.formfield_dict.values(): - if hasattr(field, 'errors'): - errors.extend(field.errors()) - return errors - - def has_errors(self): - return bool(len(self.errors())) - - def html_combined_error_list(self): - return mark_safe(''.join([field.html_error_list() for field in self.formfield_dict.values() if hasattr(field, 'errors')])) - -class InlineObjectCollection(object): - "An object that acts like a sparse list of form field collections." - def __init__(self, parent_manipulator, rel_obj, data, errors): - self.parent_manipulator = parent_manipulator - self.rel_obj = rel_obj - self.data = data - self.errors = errors - self._collections = None - self.name = rel_obj.name - # This is the name used prior to fixing #1839. Needs for backwards - # compatibility. - self.orig_name = rel_obj.opts.module_name - - def __len__(self): - self.fill() - return self._collections.__len__() - - def __getitem__(self, k): - self.fill() - return self._collections.__getitem__(k) - - def __setitem__(self, k, v): - self.fill() - return self._collections.__setitem__(k,v) - - def __delitem__(self, k): - self.fill() - return self._collections.__delitem__(k) - - def __iter__(self): - self.fill() - return iter(self._collections.values()) - - def items(self): - self.fill() - return self._collections.items() - - def fill(self): - if self._collections: - return - else: - var_name = self.rel_obj.opts.object_name.lower() - collections = {} - orig = None - if hasattr(self.parent_manipulator, 'original_object'): - orig = self.parent_manipulator.original_object - orig_list = self.rel_obj.get_list(orig) - - for i, instance in enumerate(orig_list): - collection = {'original': instance} - for f in self.rel_obj.editable_fields(): - for field_name in f.get_manipulator_field_names(''): - full_field_name = '%s.%d.%s' % (var_name, i, field_name) - field = self.parent_manipulator[full_field_name] - data = field.extract_data(self.data) - errors = self.errors.get(full_field_name, []) - collection[field_name] = FormFieldWrapper(field, data, errors) - collections[i] = FormFieldCollection(collection) - self._collections = collections - - -class FormField(object): - """Abstract class representing a form field. - - Classes that extend FormField should define the following attributes: - field_name - The field's name for use by programs. - validator_list - A list of validation tests (callback functions) that the data for - this field must pass in order to be added or changed. - is_required - A Boolean. Is it a required field? - Subclasses should also implement a render(data) method, which is responsible - for rending the form field in XHTML. - """ - - def __str__(self): - return unicode(self).encode('utf-8') - - def __unicode__(self): - return self.render(u'') - - def __repr__(self): - return 'FormField "%s"' % self.field_name - - def prepare(self, new_data): - "Hook for doing something to new_data (in place) before validation." - pass - - def html2python(data): - "Hook for converting an HTML datatype (e.g. 'on' for checkboxes) to a Python type" - return data - html2python = staticmethod(html2python) - - def render(self, data): - raise NotImplementedError - - def get_member_name(self): - if hasattr(self, 'member_name'): - return self.member_name - else: - return self.field_name - - def extract_data(self, data_dict): - if hasattr(self, 'requires_data_list') and hasattr(data_dict, 'getlist'): - data = data_dict.getlist(self.get_member_name()) - else: - data = data_dict.get(self.get_member_name(), None) - if data is None: - data = '' - return data - - def convert_post_data(self, new_data): - name = self.get_member_name() - if self.field_name in new_data: - d = new_data.getlist(self.field_name) - try: - converted_data = [self.__class__.html2python(data) for data in d] - except ValueError: - converted_data = d - new_data.setlist(name, converted_data) - else: - try: - #individual fields deal with None values themselves - new_data.setlist(name, [self.__class__.html2python(None)]) - except EmptyValue: - new_data.setlist(name, []) - - - def run_validator(self, new_data, validator): - if self.is_required or new_data.get(self.field_name, False) or hasattr(validator, 'always_test'): - if hasattr(self, 'requires_data_list'): - validator(new_data.getlist(self.field_name), new_data) - else: - validator(new_data.get(self.field_name, ''), new_data) - - def get_validation_errors(self, new_data): - errors = {} - if self.is_required and not new_data.get(self.field_name, False): - errors.setdefault(self.field_name, []).append(ugettext('This field is required.')) - return errors - try: - for validator in self.validator_list: - try: - self.run_validator(new_data, validator) - except validators.ValidationError, e: - errors.setdefault(self.field_name, []).extend(e.messages) - # If a CriticalValidationError is raised, ignore any other ValidationErrors - # for this particular field - except validators.CriticalValidationError, e: - errors.setdefault(self.field_name, []).extend(e.messages) - return errors - - def get_id(self): - "Returns the HTML 'id' attribute for this form field." - return FORM_FIELD_ID_PREFIX + self.field_name - -#################### -# GENERIC WIDGETS # -#################### - -class TextField(FormField): - input_type = "text" - def __init__(self, field_name, length=30, max_length=None, is_required=False, validator_list=None, member_name=None): - if validator_list is None: validator_list = [] - self.field_name = field_name - self.length, self.max_length = length, max_length - self.is_required = is_required - self.validator_list = [self.isValidLength, self.hasNoNewlines] + validator_list - if member_name != None: - self.member_name = member_name - - def isValidLength(self, data, form): - if data and self.max_length and len(smart_unicode(data)) > self.max_length: - raise validators.ValidationError, ungettext("Ensure your text is less than %s character.", - "Ensure your text is less than %s characters.", self.max_length) % self.max_length - - def hasNoNewlines(self, data, form): - if data and '\n' in data: - raise validators.ValidationError, ugettext("Line breaks are not allowed here.") - - def render(self, data): - if data is None: - data = u'' - max_length = u'' - if self.max_length: - max_length = u'maxlength="%s" ' % self.max_length - return mark_safe(u'<input type="%s" id="%s" class="v%s%s" name="%s" size="%s" value="%s" %s/>' % \ - (self.input_type, self.get_id(), self.__class__.__name__, self.is_required and u' required' or '', - self.field_name, self.length, escape(data), max_length)) - - def html2python(data): - return data - html2python = staticmethod(html2python) - -class PasswordField(TextField): - input_type = "password" - -class LargeTextField(TextField): - def __init__(self, field_name, rows=10, cols=40, is_required=False, validator_list=None, max_length=None): - if validator_list is None: validator_list = [] - self.field_name = field_name - self.rows, self.cols, self.is_required = rows, cols, is_required - self.validator_list = validator_list[:] - if max_length: - self.validator_list.append(self.isValidLength) - self.max_length = max_length - - def render(self, data): - if data is None: - data = '' - return mark_safe(u'<textarea id="%s" class="v%s%s" name="%s" rows="%s" cols="%s">%s</textarea>' % \ - (self.get_id(), self.__class__.__name__, self.is_required and u' required' or u'', - self.field_name, self.rows, self.cols, escape(data))) - -class HiddenField(FormField): - def __init__(self, field_name, is_required=False, validator_list=None, max_length=None): - if validator_list is None: validator_list = [] - self.field_name, self.is_required = field_name, is_required - self.validator_list = validator_list[:] - - def render(self, data): - return mark_safe(u'<input type="hidden" id="%s" name="%s" value="%s" />' % \ - (self.get_id(), self.field_name, escape(data))) - -class CheckboxField(FormField): - def __init__(self, field_name, checked_by_default=False, validator_list=None, is_required=False): - if validator_list is None: validator_list = [] - self.field_name = field_name - self.checked_by_default = checked_by_default - self.is_required = is_required - self.validator_list = validator_list[:] - - def render(self, data): - checked_html = '' - if data or (data is '' and self.checked_by_default): - checked_html = ' checked="checked"' - return mark_safe(u'<input type="checkbox" id="%s" class="v%s" name="%s"%s />' % \ - (self.get_id(), self.__class__.__name__, - self.field_name, checked_html)) - - def html2python(data): - "Convert value from browser ('on' or '') to a Python boolean" - if data == 'on': - return True - return False - html2python = staticmethod(html2python) - -class SelectField(FormField): - def __init__(self, field_name, choices=None, size=1, is_required=False, validator_list=None, member_name=None): - if validator_list is None: validator_list = [] - if choices is None: choices = [] - choices = [(k, smart_unicode(v, strings_only=True)) for k, v in choices] - self.field_name = field_name - # choices is a list of (value, human-readable key) tuples because order matters - self.choices, self.size, self.is_required = choices, size, is_required - self.validator_list = [self.isValidChoice] + validator_list - if member_name != None: - self.member_name = member_name - - def render(self, data): - output = [u'<select id="%s" class="v%s%s" name="%s" size="%s">' % \ - (self.get_id(), self.__class__.__name__, - self.is_required and u' required' or u'', self.field_name, self.size)] - str_data = smart_unicode(data) # normalize to string - for value, display_name in self.choices: - selected_html = u'' - if smart_unicode(value) == str_data: - selected_html = u' selected="selected"' - output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, force_unicode(escape(display_name)))) - output.append(u' </select>') - return mark_safe(u'\n'.join(output)) - - def isValidChoice(self, data, form): - str_data = smart_unicode(data) - str_choices = [smart_unicode(item[0]) for item in self.choices] - if str_data not in str_choices: - raise validators.ValidationError, ugettext("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data': str_data, 'choices': str_choices} - -class NullSelectField(SelectField): - "This SelectField converts blank fields to None" - def html2python(data): - if not data: - return None - return data - html2python = staticmethod(html2python) - -class RadioSelectField(FormField): - def __init__(self, field_name, choices=None, ul_class='', is_required=False, validator_list=None, member_name=None): - if validator_list is None: validator_list = [] - if choices is None: choices = [] - choices = [(k, smart_unicode(v)) for k, v in choices] - self.field_name = field_name - # choices is a list of (value, human-readable key) tuples because order matters - self.choices, self.is_required = choices, is_required - self.validator_list = [self.isValidChoice] + validator_list - self.ul_class = ul_class - if member_name != None: - self.member_name = member_name - - def render(self, data): - """ - Returns a special object, RadioFieldRenderer, that is iterable *and* - has a default unicode() rendered output. - - This allows for flexible use in templates. You can just use the default - rendering: - - {{ field_name }} - - ...which will output the radio buttons in an unordered list. - Or, you can manually traverse each radio option for special layout: - - {% for option in field_name.field_list %} - {{ option.field }} {{ option.label }}<br /> - {% endfor %} - """ - class RadioFieldRenderer: - def __init__(self, datalist, ul_class): - self.datalist, self.ul_class = datalist, ul_class - def __unicode__(self): - "Default unicode() output for this radio field -- a <ul>" - output = [u'<ul%s>' % (self.ul_class and u' class="%s"' % self.ul_class or u'')] - output.extend([u'<li>%s %s</li>' % (d['field'], d['label']) for d in self.datalist]) - output.append(u'</ul>') - return mark_safe(u''.join(output)) - def __iter__(self): - for d in self.datalist: - yield d - def __len__(self): - return len(self.datalist) - datalist = [] - str_data = smart_unicode(data) # normalize to string - for i, (value, display_name) in enumerate(self.choices): - selected_html = '' - if smart_unicode(value) == str_data: - selected_html = u' checked="checked"' - datalist.append({ - 'value': value, - 'name': display_name, - 'field': mark_safe(u'<input type="radio" id="%s" name="%s" value="%s"%s/>' % \ - (self.get_id() + u'_' + unicode(i), self.field_name, value, selected_html)), - 'label': mark_safe(u'<label for="%s">%s</label>' % \ - (self.get_id() + u'_' + unicode(i), display_name), - )}) - return RadioFieldRenderer(datalist, self.ul_class) - - def isValidChoice(self, data, form): - str_data = smart_unicode(data) - str_choices = [smart_unicode(item[0]) for item in self.choices] - if str_data not in str_choices: - raise validators.ValidationError, ugettext("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data':str_data, 'choices':str_choices} - -class NullBooleanField(SelectField): - "This SelectField provides 'Yes', 'No' and 'Unknown', mapping results to True, False or None" - def __init__(self, field_name, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - SelectField.__init__(self, field_name, choices=[('1', ugettext('Unknown')), ('2', ugettext('Yes')), ('3', ugettext('No'))], - is_required=is_required, validator_list=validator_list) - - def render(self, data): - if data is None: data = '1' - elif data == True: data = '2' - elif data == False: data = '3' - return SelectField.render(self, data) - - def html2python(data): - return {None: None, '1': None, '2': True, '3': False}[data] - html2python = staticmethod(html2python) - -class SelectMultipleField(SelectField): - requires_data_list = True - def render(self, data): - output = [u'<select id="%s" class="v%s%s" name="%s" size="%s" multiple="multiple">' % \ - (self.get_id(), self.__class__.__name__, self.is_required and u' required' or u'', - self.field_name, self.size)] - str_data_list = map(smart_unicode, data) # normalize to strings - for value, choice in self.choices: - selected_html = u'' - if smart_unicode(value) in str_data_list: - selected_html = u' selected="selected"' - output.append(u' <option value="%s"%s>%s</option>' % (escape(value), selected_html, force_unicode(escape(choice)))) - output.append(u' </select>') - return mark_safe(u'\n'.join(output)) - - def isValidChoice(self, field_data, all_data): - # data is something like ['1', '2', '3'] - str_choices = [smart_unicode(item[0]) for item in self.choices] - for val in map(smart_unicode, field_data): - if val not in str_choices: - raise validators.ValidationError, ugettext("Select a valid choice; '%(data)s' is not in %(choices)s.") % {'data':val, 'choices':str_choices} - - def html2python(data): - if data is None: - raise EmptyValue - return data - html2python = staticmethod(html2python) - -class CheckboxSelectMultipleField(SelectMultipleField): - """ - This has an identical interface to SelectMultipleField, except the rendered - widget is different. Instead of a <select multiple>, this widget outputs a - <ul> of <input type="checkbox">es. - - Of course, that results in multiple form elements for the same "single" - field, so this class's prepare() method flattens the split data elements - back into the single list that validators, renderers and save() expect. - """ - requires_data_list = True - def __init__(self, field_name, choices=None, ul_class='', validator_list=None): - if validator_list is None: validator_list = [] - if choices is None: choices = [] - self.ul_class = ul_class - SelectMultipleField.__init__(self, field_name, choices, size=1, is_required=False, validator_list=validator_list) - - def prepare(self, new_data): - # new_data has "split" this field into several fields, so flatten it - # back into a single list. - data_list = [] - for value, readable_value in self.choices: - if new_data.get('%s%s' % (self.field_name, value), '') == 'on': - data_list.append(value) - new_data.setlist(self.field_name, data_list) - - def render(self, data): - output = [u'<ul%s>' % (self.ul_class and u' class="%s"' % self.ul_class or u'')] - str_data_list = map(smart_unicode, data) # normalize to strings - for value, choice in self.choices: - checked_html = u'' - if smart_unicode(value) in str_data_list: - checked_html = u' checked="checked"' - field_name = u'%s%s' % (self.field_name, value) - output.append(u'<li><input type="checkbox" id="%s" class="v%s" name="%s"%s value="on" /> <label for="%s">%s</label></li>' % \ - (self.get_id() + escape(value), self.__class__.__name__, field_name, checked_html, - self.get_id() + escape(value), choice)) - output.append(u'</ul>') - return mark_safe(u'\n'.join(output)) - -#################### -# FILE UPLOADS # -#################### - -class FileUploadField(FormField): - def __init__(self, field_name, is_required=False, validator_list=None, max_length=None): - if validator_list is None: validator_list = [] - self.field_name, self.is_required = field_name, is_required - self.validator_list = [self.isNonEmptyFile] + validator_list - - def isNonEmptyFile(self, new_data, all_data): - if hasattr(new_data, 'upload_errors'): - upload_errors = new_data.upload_errors() - if upload_errors: - raise validators.CriticalValidationError, upload_errors - try: - file_size = new_data.size - except AttributeError: - file_size = len(new_data['content']) - if not file_size: - raise validators.CriticalValidationError, ugettext("The submitted file is empty.") - - def render(self, data): - return mark_safe(u'<input type="file" id="%s" class="v%s" name="%s" />' % \ - (self.get_id(), self.__class__.__name__, self.field_name)) - - def prepare(self, new_data): - if hasattr(new_data, 'upload_errors'): - upload_errors = new_data.upload_errors() - new_data[self.field_name] = { '_file_upload_error': upload_errors } - - def html2python(data): - if data is None: - raise EmptyValue - return data - html2python = staticmethod(html2python) - -class ImageUploadField(FileUploadField): - "A FileUploadField that raises CriticalValidationError if the uploaded file isn't an image." - def __init__(self, *args, **kwargs): - FileUploadField.__init__(self, *args, **kwargs) - self.validator_list.insert(0, self.isValidImage) - - def isValidImage(self, field_data, all_data): - try: - validators.isValidImage(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - -#################### -# INTEGERS/FLOATS # -#################### - -class IntegerField(TextField): - def __init__(self, field_name, length=10, max_length=None, is_required=False, validator_list=None, member_name=None): - if validator_list is None: validator_list = [] - validator_list = [self.isInteger] + validator_list - if member_name is not None: - self.member_name = member_name - TextField.__init__(self, field_name, length, max_length, is_required, validator_list) - - def isInteger(self, field_data, all_data): - try: - validators.isInteger(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - - def html2python(data): - if data == '' or data is None: - return None - return int(data) - html2python = staticmethod(html2python) - -class SmallIntegerField(IntegerField): - def __init__(self, field_name, length=5, max_length=5, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isSmallInteger] + validator_list - IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list) - - def isSmallInteger(self, field_data, all_data): - if not -32768 <= int(field_data) <= 32767: - raise validators.CriticalValidationError, ugettext("Enter a whole number between -32,768 and 32,767.") - -class PositiveIntegerField(IntegerField): - def __init__(self, field_name, length=10, max_length=None, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isPositive] + validator_list - IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list) - - def isPositive(self, field_data, all_data): - if int(field_data) < 0: - raise validators.CriticalValidationError, ugettext("Enter a positive number.") - -class PositiveSmallIntegerField(IntegerField): - def __init__(self, field_name, length=5, max_length=None, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isPositiveSmall] + validator_list - IntegerField.__init__(self, field_name, length, max_length, is_required, validator_list) - - def isPositiveSmall(self, field_data, all_data): - if not 0 <= int(field_data) <= 32767: - raise validators.CriticalValidationError, ugettext("Enter a whole number between 0 and 32,767.") - -class FloatField(TextField): - def __init__(self, field_name, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [validators.isValidFloat] + validator_list - TextField.__init__(self, field_name, is_required=is_required, validator_list=validator_list) - - def html2python(data): - if data == '' or data is None: - return None - return float(data) - html2python = staticmethod(html2python) - -class DecimalField(TextField): - def __init__(self, field_name, max_digits, decimal_places, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - self.max_digits, self.decimal_places = max_digits, decimal_places - validator_list = [self.isValidDecimal] + validator_list - # Initialise the TextField, making sure it's large enough to fit the number with a - sign and a decimal point. - super(DecimalField, self).__init__(field_name, max_digits+2, max_digits+2, is_required, validator_list) - - def isValidDecimal(self, field_data, all_data): - v = validators.IsValidDecimal(self.max_digits, self.decimal_places) - try: - v(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - - def html2python(data): - if data == '' or data is None: - return None - try: - import decimal - except ImportError: - from django.utils import _decimal as decimal - try: - return decimal.Decimal(data) - except decimal.InvalidOperation, e: - raise ValueError, e - html2python = staticmethod(html2python) - -#################### -# DATES AND TIMES # -#################### - -class DatetimeField(TextField): - """A FormField that automatically converts its data to a datetime.datetime object. - The data should be in the format YYYY-MM-DD HH:MM:SS.""" - def __init__(self, field_name, length=30, max_length=None, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - self.field_name = field_name - self.length, self.max_length = length, max_length - self.is_required = is_required - self.validator_list = [validators.isValidANSIDatetime] + validator_list - - def html2python(data): - "Converts the field into a datetime.datetime object" - import datetime - try: - date, time = data.split() - y, m, d = date.split('-') - timebits = time.split(':') - h, mn = timebits[:2] - if len(timebits) > 2: - s = int(timebits[2]) - else: - s = 0 - return datetime.datetime(int(y), int(m), int(d), int(h), int(mn), s) - except ValueError: - return None - html2python = staticmethod(html2python) - -class DateField(TextField): - """A FormField that automatically converts its data to a datetime.date object. - The data should be in the format YYYY-MM-DD.""" - def __init__(self, field_name, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isValidDate] + validator_list - TextField.__init__(self, field_name, length=10, max_length=10, - is_required=is_required, validator_list=validator_list) - - def isValidDate(self, field_data, all_data): - try: - validators.isValidANSIDate(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - - def html2python(data): - "Converts the field into a datetime.date object" - import time, datetime - try: - time_tuple = time.strptime(data, '%Y-%m-%d') - return datetime.date(*time_tuple[0:3]) - except (ValueError, TypeError): - return None - html2python = staticmethod(html2python) - -class TimeField(TextField): - """A FormField that automatically converts its data to a datetime.time object. - The data should be in the format HH:MM:SS or HH:MM:SS.mmmmmm.""" - def __init__(self, field_name, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isValidTime] + validator_list - TextField.__init__(self, field_name, length=8, max_length=8, - is_required=is_required, validator_list=validator_list) - - def isValidTime(self, field_data, all_data): - try: - validators.isValidANSITime(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - - def html2python(data): - "Converts the field into a datetime.time object" - import time, datetime - try: - part_list = data.split('.') - try: - time_tuple = time.strptime(part_list[0], '%H:%M:%S') - except ValueError: # seconds weren't provided - time_tuple = time.strptime(part_list[0], '%H:%M') - t = datetime.time(*time_tuple[3:6]) - if (len(part_list) == 2): - t = t.replace(microsecond=int(part_list[1])) - return t - except (ValueError, TypeError, AttributeError): - return None - html2python = staticmethod(html2python) - -#################### -# INTERNET-RELATED # -#################### - -class EmailField(TextField): - "A convenience FormField for validating e-mail addresses" - def __init__(self, field_name, length=50, max_length=75, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isValidEmail] + validator_list - TextField.__init__(self, field_name, length, max_length=max_length, - is_required=is_required, validator_list=validator_list) - - def isValidEmail(self, field_data, all_data): - try: - validators.isValidEmail(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - -class URLField(TextField): - "A convenience FormField for validating URLs" - def __init__(self, field_name, length=50, max_length=200, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isValidURL] + validator_list - TextField.__init__(self, field_name, length=length, max_length=max_length, - is_required=is_required, validator_list=validator_list) - - def isValidURL(self, field_data, all_data): - try: - validators.isValidURL(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - -class IPAddressField(TextField): - def __init__(self, field_name, length=15, max_length=15, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isValidIPAddress] + validator_list - TextField.__init__(self, field_name, length=length, max_length=max_length, - is_required=is_required, validator_list=validator_list) - - def isValidIPAddress(self, field_data, all_data): - try: - validators.isValidIPAddress4(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - - def html2python(data): - return data or None - html2python = staticmethod(html2python) - -#################### -# MISCELLANEOUS # -#################### - -class FilePathField(SelectField): - "A SelectField whose choices are the files in a given directory." - def __init__(self, field_name, path, match=None, recursive=False, is_required=False, validator_list=None, max_length=None): - import os - from django.db.models import BLANK_CHOICE_DASH - if match is not None: - import re - match_re = re.compile(match) - choices = not is_required and BLANK_CHOICE_DASH[:] or [] - if recursive: - for root, dirs, files in os.walk(path): - for f in files: - if match is None or match_re.search(f): - f = os.path.join(root, f) - choices.append((f, f.replace(path, "", 1))) - else: - try: - for f in os.listdir(path): - full_file = os.path.join(path, f) - if os.path.isfile(full_file) and (match is None or match_re.search(f)): - choices.append((full_file, f)) - except OSError: - pass - SelectField.__init__(self, field_name, choices, 1, is_required, validator_list) - -class PhoneNumberField(TextField): - "A convenience FormField for validating phone numbers (e.g. '630-555-1234')" - def __init__(self, field_name, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isValidPhone] + validator_list - TextField.__init__(self, field_name, length=12, max_length=12, - is_required=is_required, validator_list=validator_list) - - def isValidPhone(self, field_data, all_data): - try: - validators.isValidPhone(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - -class USStateField(TextField): - "A convenience FormField for validating U.S. states (e.g. 'IL')" - def __init__(self, field_name, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isValidUSState] + validator_list - TextField.__init__(self, field_name, length=2, max_length=2, - is_required=is_required, validator_list=validator_list) - - def isValidUSState(self, field_data, all_data): - try: - validators.isValidUSState(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - - def html2python(data): - if data: - return data.upper() # Should always be stored in upper case - return data - html2python = staticmethod(html2python) - -class CommaSeparatedIntegerField(TextField): - "A convenience FormField for validating comma-separated integer fields" - def __init__(self, field_name, max_length=None, is_required=False, validator_list=None): - if validator_list is None: validator_list = [] - validator_list = [self.isCommaSeparatedIntegerList] + validator_list - TextField.__init__(self, field_name, length=20, max_length=max_length, - is_required=is_required, validator_list=validator_list) - - def isCommaSeparatedIntegerList(self, field_data, all_data): - try: - validators.isCommaSeparatedIntegerList(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages - - def render(self, data): - if data is None: - data = u'' - elif isinstance(data, (list, tuple)): - data = u','.join(data) - return super(CommaSeparatedIntegerField, self).render(data) - -class RawIdAdminField(CommaSeparatedIntegerField): - def html2python(data): - if data: - return data.split(',') - else: - return [] - html2python = staticmethod(html2python) - -class XMLLargeTextField(LargeTextField): - """ - A LargeTextField with an XML validator. The schema_path argument is the - full path to a Relax NG compact schema to validate against. - """ - def __init__(self, field_name, schema_path, **kwargs): - self.schema_path = schema_path - kwargs.setdefault('validator_list', []).insert(0, self.isValidXML) - LargeTextField.__init__(self, field_name, **kwargs) - - def isValidXML(self, field_data, all_data): - v = validators.RelaxNGCompact(self.schema_path) - try: - v(field_data, all_data) - except validators.ValidationError, e: - raise validators.CriticalValidationError, e.messages |
