PageRenderTime 167ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/django/contrib/localflavor/ch/forms.py

https://code.google.com/p/mango-py/
Python | 118 lines | 108 code | 5 blank | 5 comment | 2 complexity | 495e93873445ba38fdedf3bf7cf706c2 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. """
  2. Swiss-specific Form helpers
  3. """
  4. from django.core.validators import EMPTY_VALUES
  5. from django.forms import ValidationError
  6. from django.forms.fields import Field, RegexField, Select
  7. from django.utils.encoding import smart_unicode
  8. from django.utils.translation import ugettext_lazy as _
  9. import re
  10. id_re = re.compile(r"^(?P<idnumber>\w{8})(?P<pos9>(\d{1}|<))(?P<checksum>\d{1})$")
  11. phone_digits_re = re.compile(r'^0([1-9]{1})\d{8}$')
  12. class CHZipCodeField(RegexField):
  13. default_error_messages = {
  14. 'invalid': _('Enter a zip code in the format XXXX.'),
  15. }
  16. def __init__(self, *args, **kwargs):
  17. super(CHZipCodeField, self).__init__(r'^\d{4}$',
  18. max_length=None, min_length=None, *args, **kwargs)
  19. class CHPhoneNumberField(Field):
  20. """
  21. Validate local Swiss phone number (not international ones)
  22. The correct format is '0XX XXX XX XX'.
  23. '0XX.XXX.XX.XX' and '0XXXXXXXXX' validate but are corrected to
  24. '0XX XXX XX XX'.
  25. """
  26. default_error_messages = {
  27. 'invalid': 'Phone numbers must be in 0XX XXX XX XX format.',
  28. }
  29. def clean(self, value):
  30. super(CHPhoneNumberField, self).clean(value)
  31. if value in EMPTY_VALUES:
  32. return u''
  33. value = re.sub('(\.|\s|/|-)', '', smart_unicode(value))
  34. m = phone_digits_re.search(value)
  35. if m:
  36. return u'%s %s %s %s' % (value[0:3], value[3:6], value[6:8], value[8:10])
  37. raise ValidationError(self.error_messages['invalid'])
  38. class CHStateSelect(Select):
  39. """
  40. A Select widget that uses a list of CH states as its choices.
  41. """
  42. def __init__(self, attrs=None):
  43. from ch_states import STATE_CHOICES # relative import
  44. super(CHStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
  45. class CHIdentityCardNumberField(Field):
  46. """
  47. A Swiss identity card number.
  48. Checks the following rules to determine whether the number is valid:
  49. * Conforms to the X1234567<0 or 1234567890 format.
  50. * Included checksums match calculated checksums
  51. """
  52. default_error_messages = {
  53. 'invalid': _('Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.'),
  54. }
  55. def has_valid_checksum(self, number):
  56. given_number, given_checksum = number[:-1], number[-1]
  57. new_number = given_number
  58. calculated_checksum = 0
  59. fragment = ""
  60. parameter = 7
  61. first = str(number[:1])
  62. if first.isalpha():
  63. num = ord(first.upper()) - 65
  64. if num < 0 or num > 8:
  65. return False
  66. new_number = str(num) + new_number[1:]
  67. new_number = new_number[:8] + '0'
  68. if not new_number.isdigit():
  69. return False
  70. for i in range(len(new_number)):
  71. fragment = int(new_number[i])*parameter
  72. calculated_checksum += fragment
  73. if parameter == 1:
  74. parameter = 7
  75. elif parameter == 3:
  76. parameter = 1
  77. elif parameter ==7:
  78. parameter = 3
  79. return str(calculated_checksum)[-1] == given_checksum
  80. def clean(self, value):
  81. super(CHIdentityCardNumberField, self).clean(value)
  82. if value in EMPTY_VALUES:
  83. return u''
  84. match = re.match(id_re, value)
  85. if not match:
  86. raise ValidationError(self.error_messages['invalid'])
  87. idnumber, pos9, checksum = match.groupdict()['idnumber'], match.groupdict()['pos9'], match.groupdict()['checksum']
  88. if idnumber == '00000000' or \
  89. idnumber == 'A0000000':
  90. raise ValidationError(self.error_messages['invalid'])
  91. all_digits = "%s%s%s" % (idnumber, pos9, checksum)
  92. if not self.has_valid_checksum(all_digits):
  93. raise ValidationError(self.error_messages['invalid'])
  94. return u'%s%s%s' % (idnumber, pos9, checksum)