| 1 | """ |
| 2 | TR-specific Form helpers |
| 3 | """ |
| 4 | |
| 5 | from django.core.validators import EMPTY_VALUES |
| 6 | from django.forms import ValidationError |
| 7 | from django.forms.fields import Field, RegexField, Select, CharField |
| 8 | from django.utils.encoding import smart_unicode |
| 9 | from django.utils.translation import ugettext_lazy as _ |
| 10 | import re |
| 11 | |
| 12 | phone_digits_re = re.compile(r'^(\+90|0)? ?(([1-9]\d{2})|\([1-9]\d{2}\)) ?([2-9]\d{2} ?\d{2} ?\d{2})$') |
| 13 | |
| 14 | class TRZipCodeField(RegexField): |
| 15 | default_error_messages = { |
| 16 | 'invalid': _('Enter a zip code in the format XXXXX.'), |
| 17 | } |
| 18 | |
| 19 | def __init__(self, *args, **kwargs): |
| 20 | super(TRZipCodeField, self).__init__(r'^\d{5}$', |
| 21 | max_length=None, min_length=None, *args, **kwargs) |
| 22 | |
| 23 | class TRPhoneNumberField(CharField): |
| 24 | default_error_messages = { |
| 25 | 'invalid': _('Phone numbers must be in 0XXX XXX XXXX format.'), |
| 26 | } |
| 27 | |
| 28 | def clean(self, value): |
| 29 | super(TRPhoneNumberField, self).clean(value) |
| 30 | if value in EMPTY_VALUES: |
| 31 | return u'' |
| 32 | value = re.sub('(\(|\)|\s+)', '', smart_unicode(value)) |
| 33 | m = phone_digits_re.search(value) |
| 34 | if m: |
| 35 | return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3)) |
| 36 | raise ValidationError(self.error_messages['invalid']) |
| 37 | |
| 38 | class TRIdentificationNumberField(Field): |
| 39 | """ |
| 40 | A Turkey Identification Number number. |
| 41 | See: http://tr.wikipedia.org/wiki/T%C3%BCrkiye_Cumhuriyeti_Kimlik_Numaras%C4%B1 |
| 42 | |
| 43 | Checks the following rules to determine whether the number is valid: |
| 44 | |
| 45 | * The number is 11-digits. |
| 46 | * First digit is not 0. |
| 47 | * Conforms to the following two formula: |
| 48 | (sum(1st, 3rd, 5th, 7th, 9th)*7 - sum(2nd,4th,6th,8th)) % 10 = 10th digit |
| 49 | sum(1st to 10th) % 10 = 11th digit |
| 50 | """ |
| 51 | default_error_messages = { |
| 52 | 'invalid': _('Enter a valid Turkish Identification number.'), |
| 53 | 'not_11': _('Turkish Identification number must be 11 digits.'), |
| 54 | } |
| 55 | |
| 56 | def clean(self, value): |
| 57 | super(TRIdentificationNumberField, self).clean(value) |
| 58 | if value in EMPTY_VALUES: |
| 59 | return u'' |
| 60 | if len(value) != 11: |
| 61 | raise ValidationError(self.error_messages['not_11']) |
| 62 | if int(value[0]) == 0: |
| 63 | raise ValidationError(self.error_messages['invalid']) |
| 64 | chksum = (sum([int(value[i]) for i in xrange(0,9,2)])*7- |
| 65 | sum([int(value[i]) for i in xrange(1,9,2)])) % 10 |
| 66 | if chksum != int(value[9]) or \ |
| 67 | (sum([int(value[i]) for i in xrange(10)]) % 10) != int(value[10]): |
| 68 | raise ValidationError(self.error_messages['invalid']) |
| 69 | return u'%s' % (value) |
| 70 | |
| 71 | class TRProvinceSelect(Select): |
| 72 | """ |
| 73 | A Select widget that uses a list of Turkey cities as its choices. |
| 74 | """ |
| 75 | def __init__(self, attrs=None): |
| 76 | from tr_provinces import PROVINCE_CHOICES |
| 77 | super(TRProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES) |