~ubuntu-branches/ubuntu/quantal/python-django/quantal

« back to all changes in this revision

Viewing changes to django/forms/fields.py

  • Committer: Bazaar Package Importer
  • Author(s): Chris Lamb
  • Date: 2009-07-29 11:26:28 UTC
  • mfrom: (1.1.8 upstream) (4.1.5 sid)
  • Revision ID: james.westby@ubuntu.com-20090729112628-pg09ino8sz0sj21t
Tags: 1.1-1
* New upstream release.
* Merge from experimental:
  - Ship FastCGI initscript and /etc/default file in python-django's examples
    directory (Closes: #538863)
  - Drop "05_10539-sphinx06-compatibility.diff"; it has been applied
    upstream.
  - Bump Standards-Version to 3.8.2.

Show diffs side-by-side

added added

removed removed

Lines of Context:
28
28
from django.utils.encoding import smart_unicode, smart_str
29
29
 
30
30
from util import ErrorList, ValidationError
31
 
from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget
 
31
from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget
32
32
from django.core.files.uploadedfile import SimpleUploadedFile as UploadedFile
33
33
 
34
34
__all__ = (
256
256
        digits = len(digittuple)
257
257
        if decimals > digits:
258
258
            # We have leading zeros up to or past the decimal point.  Count
259
 
            # everything past the decimal point as a digit.  We do not count 
260
 
            # 0 before the decimal point as a digit since that would mean 
 
259
            # everything past the decimal point as a digit.  We do not count
 
260
            # 0 before the decimal point as a digit since that would mean
261
261
            # we would not allow max_digits = decimal_places.
262
262
            digits = decimals
263
263
        whole_digits = digits - decimals
283
283
)
284
284
 
285
285
class DateField(Field):
 
286
    widget = DateInput
286
287
    default_error_messages = {
287
288
        'invalid': _(u'Enter a valid date.'),
288
289
    }
421
422
email_re = re.compile(
422
423
    r"(^[-!#$%&'*+/=?^_`{}|~0-9A-Z]+(\.[-!#$%&'*+/=?^_`{}|~0-9A-Z]+)*"  # dot-atom
423
424
    r'|^"([\001-\010\013\014\016-\037!#-\[\]-\177]|\\[\001-011\013\014\016-\177])*"' # quoted-string
424
 
    r')@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}$', re.IGNORECASE)  # domain
 
425
    r')@(?:[A-Z0-9]+(?:-*[A-Z0-9]+)*\.)+[A-Z]{2,6}$', re.IGNORECASE)  # domain
425
426
 
426
427
class EmailField(RegexField):
427
428
    default_error_messages = {
446
447
        'invalid': _(u"No file was submitted. Check the encoding type on the form."),
447
448
        'missing': _(u"No file was submitted."),
448
449
        'empty': _(u"The submitted file is empty."),
 
450
        'max_length': _(u'Ensure this filename has at most %(max)d characters (it has %(length)d).'),
449
451
    }
450
452
 
451
453
    def __init__(self, *args, **kwargs):
 
454
        self.max_length = kwargs.pop('max_length', None)
452
455
        super(FileField, self).__init__(*args, **kwargs)
453
456
 
454
457
    def clean(self, data, initial=None):
465
468
        except AttributeError:
466
469
            raise ValidationError(self.error_messages['invalid'])
467
470
 
 
471
        if self.max_length is not None and len(file_name) > self.max_length:
 
472
            error_values =  {'max': self.max_length, 'length': len(file_name)}
 
473
            raise ValidationError(self.error_messages['max_length'] % error_values)
468
474
        if not file_name:
469
475
            raise ValidationError(self.error_messages['invalid'])
470
476
        if not file_size:
527
533
 
528
534
url_re = re.compile(
529
535
    r'^https?://' # http:// or https://
530
 
    r'(?:(?:[A-Z0-9-]+\.)+[A-Z]{2,6}|' #domain...
 
536
    r'(?:(?:[A-Z0-9]+(?:-*[A-Z0-9]+)*\.)+[A-Z]{2,6}|' #domain...
531
537
    r'localhost|' #localhost...
532
538
    r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip
533
539
    r'(?::\d+)?' # optional port
580
586
    def clean(self, value):
581
587
        """Returns a Python boolean object."""
582
588
        # Explicitly check for the string 'False', which is what a hidden field
583
 
        # will submit for False. Because bool("True") == True, we don't need to
584
 
        # handle that explicitly.
585
 
        if value == 'False':
 
589
        # will submit for False. Also check for '0', since this is what
 
590
        # RadioSelect will provide. Because bool("True") == bool('1') == True,
 
591
        # we don't need to handle that explicitly.
 
592
        if value in ('False', '0'):
586
593
            value = False
587
594
        else:
588
595
            value = bool(value)
601
608
    def clean(self, value):
602
609
        """
603
610
        Explicitly checks for the string 'True' and 'False', which is what a
604
 
        hidden field will submit for True and False. Unlike the
605
 
        Booleanfield we also need to check for True, because we are not using
606
 
        the bool() function
 
611
        hidden field will submit for True and False, and for '1' and '0', which
 
612
        is what a RadioField will submit. Unlike the Booleanfield we need to
 
613
        explicitly check for True, because we are not using the bool() function
607
614
        """
608
 
        if value in (True, 'True'):
 
615
        if value in (True, 'True', '1'):
609
616
            return True
610
 
        elif value in (False, 'False'):
 
617
        elif value in (False, 'False', '0'):
611
618
            return False
612
619
        else:
613
620
            return None
823
830
        super(FilePathField, self).__init__(choices=(), required=required,
824
831
            widget=widget, label=label, initial=initial, help_text=help_text,
825
832
            *args, **kwargs)
826
 
        self.choices = []
 
833
 
 
834
        if self.required:
 
835
            self.choices = []
 
836
        else:
 
837
            self.choices = [("", "---------")]
 
838
 
827
839
        if self.match is not None:
828
840
            self.match_re = re.compile(self.match)
 
841
 
829
842
        if recursive:
830
843
            for root, dirs, files in os.walk(self.path):
831
844
                for f in files:
840
853
                        self.choices.append((full_file, f))
841
854
            except OSError:
842
855
                pass
 
856
 
843
857
        self.widget.choices = self.choices
844
858
 
845
859
class SplitDateTimeField(MultiValueField):
850
864
        'invalid_time': _(u'Enter a valid time.'),
851
865
    }
852
866
 
853
 
    def __init__(self, *args, **kwargs):
 
867
    def __init__(self, input_date_formats=None, input_time_formats=None, *args, **kwargs):
854
868
        errors = self.default_error_messages.copy()
855
869
        if 'error_messages' in kwargs:
856
870
            errors.update(kwargs['error_messages'])
857
871
        fields = (
858
 
            DateField(error_messages={'invalid': errors['invalid_date']}),
859
 
            TimeField(error_messages={'invalid': errors['invalid_time']}),
 
872
            DateField(input_formats=input_date_formats, error_messages={'invalid': errors['invalid_date']}),
 
873
            TimeField(input_formats=input_time_formats, error_messages={'invalid': errors['invalid_time']}),
860
874
        )
861
875
        super(SplitDateTimeField, self).__init__(fields, *args, **kwargs)
862
876