Ticket #2443: durationfield.7.diff
File durationfield.7.diff, 6.9 KB (added by , 16 years ago) |
---|
-
django/db/models/fields/__init__.py
636 636 defaults.update(kwargs) 637 637 return super(DecimalField, self).formfield(**defaults) 638 638 639 class DurationProxy(object): 640 def __init__(self, field): 641 self.field_name = field.name 642 643 def __get__(self, instance=None, owner=None): 644 if instance is None: 645 raise AttributeError, "%s can only be accessed from %s instances." % (self.field_name, owner.__name__) 646 if self.field_name not in instance.__dict__: 647 return None 648 return instance.__dict__[self.field_name] 649 650 def __set__(self, instance, value): 651 if value and not isinstance(value, datetime.timedelta): 652 value = datetime.timedelta(seconds=float(value)) 653 instance.__dict__[self.field_name] = value 654 655 class DurationField(Field): 656 def __init__(self, *args, **kwargs): 657 super(DurationField, self).__init__(*args, **kwargs) 658 self.max_digits, self.decimal_places = 20, 6 659 660 def get_internal_type(self): 661 return "DecimalField" 662 663 def contribute_to_class(self, cls, name): 664 super(DurationField, self).contribute_to_class(cls, name) 665 setattr(cls, name, DurationProxy(self)) 666 667 def get_db_prep_save(self, value): 668 if value is None: 669 return None 670 return str(value.days * 24 * 3600 + value.seconds + float(value.microseconds) / 1000000) 671 672 def to_python(self, value): 673 if isinstance(value, datetime.timedelta): 674 return value 675 try: 676 return datetime.timedelta(seconds=float(value)) 677 except (TypeError, ValueError): 678 raise validators.ValidationError('This value must be a real number.') 679 except OverflowError: 680 raise validators.ValidationError('The maximum allowed value is %s' % datetime.timedelta.max) 681 682 def flatten_data(self, follow, obj=None): 683 val = self._get_val_from_obj(obj) 684 if val is None or val is '': 685 return '' 686 return {self.name: self.get_db_prep_save(val)} 687 688 def formfield(self, form_class=forms.DurationField, **kwargs): 689 return super(DurationField, self).formfield(form_class, **kwargs) 690 691 def get_manipulator_field_objs(self): 692 return [curry(oldforms.DecimalField, max_digits=self.max_digits, decimal_places=self.decimal_places)] 693 639 694 class EmailField(CharField): 640 695 def __init__(self, *args, **kwargs): 641 696 kwargs['max_length'] = kwargs.get('max_length', 75) -
django/forms/fields.py
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, DateInput, DateTimeInput, TimeInput, SplitDateTimeWidget, SplitHiddenDateTimeWidget31 from widgets import TextInput, PasswordInput, HiddenInput, MultipleHiddenInput, FileInput, CheckboxInput, Select, NullBooleanSelect, SelectMultiple, DateInput, DateTimeInput, TimeInput, DurationWidget, SplitDateTimeWidget, SplitHiddenDateTimeWidget 32 32 from django.core.files.uploadedfile import SimpleUploadedFile as UploadedFile 33 33 34 34 __all__ = ( … … 40 40 'BooleanField', 'NullBooleanField', 'ChoiceField', 'MultipleChoiceField', 41 41 'ComboField', 'MultiValueField', 'FloatField', 'DecimalField', 42 42 'SplitDateTimeField', 'IPAddressField', 'FilePathField', 'SlugField', 43 'TypedChoiceField' 43 'TypedChoiceField', 'DurationField', 44 44 ) 45 45 46 46 # These values, if given to to_python(), will trigger the self.required check. … … 884 884 return datetime.datetime.combine(*data_list) 885 885 return None 886 886 887 class DurationField(MultiValueField): 888 widget = DurationWidget 889 890 def __init__(self, *args, **kwargs): 891 errors = self.default_error_messages.copy() 892 fields = ( 893 IntegerField(max_value=999999999, min_value=-999999999), 894 IntegerField(label='Hours', max_value=23, min_value=0), 895 IntegerField(label='Minutes', max_value=59, min_value=0), 896 IntegerField(label='Seconds', max_value=59, min_value=0), 897 IntegerField(label='Microseconds', max_value=999999, min_value=0), 898 ) 899 super(DurationField, self).__init__(fields, *args, **kwargs) 900 901 def compress(self, data_list): 902 if data_list == [None] * 5: 903 raise ValidationError(gettext(u'This field is required.')) 904 if data_list: 905 return datetime.timedelta( 906 days=data_list[0] or 0, 907 hours=data_list[1] or 0, 908 minutes=data_list[2] or 0, 909 seconds=data_list[3] or 0, 910 microseconds=data_list[4] or 0, 911 ) 912 return None 913 887 914 ipv4_re = re.compile(r'^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$') 888 915 889 916 class IPAddressField(RegexField): -
django/forms/widgets.py
26 26 'FileInput', 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', 'CheckboxInput', 27 27 'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', 28 28 'CheckboxSelectMultiple', 'MultiWidget', 29 'SplitDateTimeWidget', 29 'SplitDateTimeWidget', 'DurationWidget', 30 30 ) 31 31 32 32 MEDIA_TYPES = ('css','js') … … 706 706 def __init__(self, attrs=None): 707 707 widgets = (HiddenInput(attrs=attrs), HiddenInput(attrs=attrs)) 708 708 super(SplitDateTimeWidget, self).__init__(widgets, attrs) 709 710 class DurationWidget(MultiWidget): 711 def __init__(self, attrs=None): 712 attrs = attrs or {} 713 widgets = ( 714 TextInput(attrs=dict(attrs, size=4, maxlength=10, title='Days')), 715 TextInput(attrs=dict(attrs, size=1, maxlength=2, title='Hours')), 716 TextInput(attrs=dict(attrs, size=1, maxlength=2, title='Minutes')), 717 TextInput(attrs=dict(attrs, size=1, maxlength=2, title='Seconds')), 718 TextInput(attrs=dict(attrs, size=5, maxlength=6, title='Microseconds')), 719 ) 720 super(DurationWidget, self).__init__(widgets, attrs) 721 722 def decompress(self, value): 723 if value: 724 hours, seconds = divmod(value.seconds, 3600) 725 minutes, seconds = divmod(seconds, 60) 726 return [value.days, hours, minutes, seconds, value.microseconds] 727 return [None, None, None, None, None] 728 729 def format_output(self, rendered_widgets): 730 return u'%s days, %s : %s : %s . %s' % tuple(rendered_widgets)