forms.py 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. from datetime import datetime, timedelta
  2. from mptt.forms import * # noqa
  3. from django.forms import * # noqa
  4. from django.utils import timezone
  5. from django.utils.encoding import force_text
  6. from django.utils.translation import ugettext_lazy as _
  7. class YesNoSwitchBase(TypedChoiceField):
  8. def prepare_value(self, value):
  9. """normalize bools to binary 1/0 so field works on them too"""
  10. if value in (True, 'True', 'true', 1, '1'):
  11. return 1
  12. else:
  13. return 0
  14. def clean(self, value):
  15. return self.prepare_value(value)
  16. def YesNoSwitch(**kwargs):
  17. yes_label = kwargs.pop('yes_label', _("Yes"))
  18. no_label = kwargs.pop('no_label', _("No"))
  19. return YesNoSwitchBase(
  20. coerce=int,
  21. choices=((1, yes_label), (0, no_label)),
  22. widget=RadioSelect(attrs={'class': 'yesno-switch'}),
  23. **kwargs)
  24. class IsoDateTimeField(DateTimeField):
  25. input_formats = ['iso8601']
  26. iso8601_formats = (
  27. "%Y-%m-%dT%H:%M:%S",
  28. "%Y-%m-%dT%H:%M:%S+00:00",
  29. "%Y-%m-%dT%H:%M:%S.%f",
  30. "%Y-%m-%dT%H:%M:%S.%f+00:00")
  31. def prepare_value(self, value):
  32. try:
  33. return value.isoformat()
  34. except AttributeError:
  35. return value
  36. def strptime(self, value):
  37. for format in self.iso8601_formats:
  38. try:
  39. return datetime.strptime(value, format)
  40. except ValueError:
  41. pass
  42. else:
  43. raise ValueError()
  44. def to_python(self, value):
  45. """
  46. Validates that the input can be converted to a datetime. Returns a
  47. Python datetime.datetime object.
  48. """
  49. if value in self.empty_values:
  50. return None
  51. try:
  52. unicode_value = force_text(value, strings_only=True)
  53. date = unicode_value[:-6]
  54. offset = unicode_value[-6:]
  55. local_date = self.strptime(value)
  56. if offset and offset[0] in ('-', '+'):
  57. tz_offset = timedelta(hours=int(offset[1:3]), minutes=int(offset[4:6]))
  58. tz_offset = tz_offset.seconds // 60
  59. if offset[0] == '-':
  60. tz_offset *= -1
  61. else:
  62. tz_offset = 0
  63. tz_correction = timezone.get_fixed_timezone(tz_offset)
  64. return timezone.make_aware(local_date, tz_correction)
  65. except (IndexError, TypeError, ValueError) as e:
  66. raise ValidationError(
  67. self.error_messages['invalid'], code='invalid')