forms.py 2.8 KB

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