Ticket #4964: brlocalflavor.diff
File brlocalflavor.diff, 11.4 KB (added by , 17 years ago) |
---|
-
django/contrib/localflavor/br/forms.py
1 1 # -*- coding: utf-8 -*- 2 2 """ 3 3 BR-specific Form helpers 4 5 Usage: 6 7 >>> from django.contrib.localflavor.br.forms import * 8 >>> from django import newforms as forms 9 >>> class BRForm(forms.Form): 10 ... zipcode = BRZipCodeField() 11 ... phone = BRPhoneNumberField() 12 ... state = BRStateChoiceField() 13 ... cpf = BRCPFField() 14 ... cnpj = BRCNPJField() 15 ... 16 >>> f = BRForm() 17 >>> print f.as_ul() 18 ... 19 >>> print f.as_table() 20 ... 21 >>> print f.as_p() 22 23 24 >>> data = {'zipcode': '12345-123', 25 ... 'phone': '41 3562 3464', 26 ... 'state': 'PR', 27 ... 'cpf': '663.256.017-26', 28 ... 'cnpj': '64.132.916/0001-88'} 29 >>> f = BRForm(data) 30 >>> f.is_valid() 31 True 4 32 """ 5 33 34 import re 35 from django.utils.translation import ugettext 36 from django.utils.encoding import smart_unicode 6 37 from django.newforms import ValidationError 7 from django.newforms.fields import Field, RegexField, CharField, Select, EMPTY_VALUES 8 from django.utils.encoding import smart_unicode 9 from django.utils.translation import ugettext 10 import re 38 from django.newforms.fields import (Field, RegexField, 39 CharField, Select, 40 EMPTY_VALUES) 11 41 12 42 phone_digits_re = re.compile(r'^(\d{2})[-\.]?(\d{4})[-\.]?(\d{4})$') 13 43 14 44 class BRZipCodeField(RegexField): 45 """ 46 A field that checks brazilian zipcode format. 47 """ 15 48 def __init__(self, *args, **kwargs): 49 error = ugettext('Enter a zip code in the format XXXXX-XXX.') 16 50 super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$', 17 max_length=None, min_length=None, 18 error_message=ugettext('Enter a zip code in the format XXXXX-XXX.'), 19 *args, **kwargs) 51 max_length=None, 52 min_length=None, 53 error_message=error, 54 *args, 55 **kwargs) 20 56 21 57 class BRPhoneNumberField(Field): 58 """ 59 A field that checks brazilian phone number format. 60 """ 22 61 def clean(self, value): 23 62 super(BRPhoneNumberField, self).clean(value) 24 63 if value in EMPTY_VALUES: … … 27 66 m = phone_digits_re.search(value) 28 67 if m: 29 68 return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3)) 30 raise ValidationError(ugettext('Phone numbers must be in XX-XXXX-XXXX format.')) 69 raise ValidationError(ugettext('Phone numbers must be' 70 ' in XX-XXXX-XXXX format.')) 31 71 32 class BRState Select(Select):72 class BRStateChoiceField(Field): 33 73 """ 34 A Select widget that uses a list of Brazilian states/territories 35 as its choices. 74 A choice field that uses a list of Brazilian states as its choices. 36 75 """ 37 def __init__(self, attrs=None): 76 widget = Select 77 78 def __init__(self, required=True, widget=None, label=None, 79 initial=None, help_text=None): 80 super(BRStateChoiceField, self).__init__(required, widget, label, 81 initial, help_text) 38 82 from br_states import STATE_CHOICES 39 s uper(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES)83 self.widget.choices = STATE_CHOICES 40 84 85 def clean(self, value): 86 value = super(BRStateChoiceField, self).clean(value) 87 if value in EMPTY_VALUES: 88 value = u'' 89 value = smart_unicode(value) 90 if value == u'': 91 return value 92 valid_values = set([smart_unicode(k) for k, v in self.widget.choices]) 93 if value not in valid_values: 94 raise ValidationError(ugettext(u'Select a valid brazilian state.' 95 ' That state is not one' 96 ' of the available states.')) 97 return value 41 98 99 100 42 101 def DV_maker(v): 43 102 if v >= 2: 44 103 return 11 - v … … 46 105 47 106 class BRCPFField(CharField): 48 107 """ 49 This field validate a CPF number or a CPF string. A CPF number is 50 compounded by XXX.XXX.XXX-VD. The two last digits are check digits. 108 This field validate a CPF(Natural Persons Register) number or string. 109 A CPF is compounded by XXX.XXX.XXX-VD. The two last digits are check 110 digits. 111 Value can be either a string in the format XXX.XXX.XXX-XX or an 112 11-digit number. 51 113 52 114 More information: 53 115 http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas 54 116 """ 55 117 def __init__(self, *args, **kwargs): 56 super(BRCPFField, self).__init__(max_length=14, min_length=11, *args, **kwargs) 118 super(BRCPFField, self).__init__(max_length=14, min_length=11, 119 *args, **kwargs) 57 120 58 121 def clean(self, value): 59 """60 Value can be either a string in the format XXX.XXX.XXX-XX or an61 11-digit number.62 """63 122 value = super(BRCPFField, self).clean(value) 64 123 if value in EMPTY_VALUES: 65 124 return u'' 66 125 orig_value = value[:] 67 126 if not value.isdigit(): 68 value = re.sub( "[-\.]", "", value)127 value = re.sub('[-\.]', '', value) 69 128 try: 70 129 int(value) 71 130 except ValueError: 72 raise ValidationError(ugettext("This field requires only numbers.")) 131 raise ValidationError(ugettext('This field requires' 132 ' only numbers.')) 73 133 if len(value) != 11: 74 raise ValidationError(ugettext("This field requires at most 11 digits or 14 characters.")) 134 raise ValidationError(ugettext('This field requires at most' 135 ' 11 digits or 14 characters.')) 75 136 orig_dv = value[-2:] 76 137 77 new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(10, 1, -1))]) 138 new_1dv = sum([i * int(value[idx]) \ 139 for idx, i in enumerate(range(10, 1, -1))]) 78 140 new_1dv = DV_maker(new_1dv % 11) 79 141 value = value[:-2] + str(new_1dv) + value[-1] 80 new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(range(11, 1, -1))]) 142 new_2dv = sum([i * int(value[idx]) \ 143 for idx, i in enumerate(range(11, 1, -1))]) 81 144 new_2dv = DV_maker(new_2dv % 11) 82 145 value = value[:-1] + str(new_2dv) 83 146 if value[-2:] != orig_dv: 84 raise ValidationError(ugettext( "Invalid CPF number."))147 raise ValidationError(ugettext('Invalid CPF number.')) 85 148 86 149 return orig_value 87 150 88 151 class BRCNPJField(Field): 152 """ 153 This field validate a CNPJ(National Registry of Corporations). 154 Value can be either a string in the format XX.XXX.XXX/XXXX-XX or a 155 group of 14 characters. 156 157 """ 89 158 def clean(self, value): 90 """91 Value can be either a string in the format XX.XXX.XXX/XXXX-XX or a92 group of 14 characters.93 """94 159 value = super(BRCNPJField, self).clean(value) 95 160 if value in EMPTY_VALUES: 96 161 return u'' 97 162 orig_value = value[:] 98 163 if not value.isdigit(): 99 value = re.sub( "[-/\.]", "", value)164 value = re.sub('[-/\.]', '', value) 100 165 try: 101 166 int(value) 102 167 except ValueError: 103 raise ValidationError( "This field requires only numbers.")168 raise ValidationError('This field requires only numbers.') 104 169 if len(value) != 14: 105 raise ValidationError( 106 ugettext("This field requires at least 14 digits"))170 raise ValidationError(ugettext('This field requires at' 171 ' least 14 digits')) 107 172 orig_dv = value[-2:] 108 173 109 new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(5, 1, -1) + range(9, 1, -1))]) 174 new_1dv = sum([i * int(value[idx]) \ 175 for idx, i in enumerate(range(5, 1, -1) + 176 range(9, 1, -1))]) 110 177 new_1dv = DV_maker(new_1dv % 11) 111 178 value = value[:-2] + str(new_1dv) + value[-1] 112 new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(range(6, 1, -1) + range(9, 1, -1))]) 179 new_2dv = sum([i * int(value[idx]) \ 180 for idx, i in enumerate(range(6, 1, -1) + 181 range(9, 1, -1))]) 113 182 new_2dv = DV_maker(new_2dv % 11) 114 183 value = value[:-1] + str(new_2dv) 115 184 if value[-2:] != orig_dv: 116 raise ValidationError(ugettext( "Invalid CNPJ number."))185 raise ValidationError(ugettext('Invalid CNPJ number.')) 117 186 118 187 return orig_value 119 188 189 # Widgets 190 class BRStateSelect(Select): 191 """ 192 A Select widget that uses a list of Brazilian states as its choices. 193 """ 194 def __init__(self, attrs=None): 195 from br_states import STATE_CHOICES 196 super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES) -
tests/regressiontests/forms/localflavor.py
980 980 >>> w.render('states', 'PR') 981 981 u'<select name="states">\n<option value="AC">Acre</option>\n<option value="AL">Alagoas</option>\n<option value="AP">Amap\xe1</option>\n<option value="AM">Amazonas</option>\n<option value="BA">Bahia</option>\n<option value="CE">Cear\xe1</option>\n<option value="DF">Distrito Federal</option>\n<option value="ES">Esp\xedrito Santo</option>\n<option value="GO">Goi\xe1s</option>\n<option value="MA">Maranh\xe3o</option>\n<option value="MT">Mato Grosso</option>\n<option value="MS">Mato Grosso do Sul</option>\n<option value="MG">Minas Gerais</option>\n<option value="PA">Par\xe1</option>\n<option value="PB">Para\xedba</option>\n<option value="PR" selected="selected">Paran\xe1</option>\n<option value="PE">Pernambuco</option>\n<option value="PI">Piau\xed</option>\n<option value="RJ">Rio de Janeiro</option>\n<option value="RN">Rio Grande do Norte</option>\n<option value="RS">Rio Grande do Sul</option>\n<option value="RO">Rond\xf4nia</option>\n<option value="RR">Roraima</option>\n<option value="SC">Santa Catarina</option>\n<option value="SP">S\xe3o Paulo</option>\n<option value="SE">Sergipe</option>\n<option value="TO">Tocantins</option>\n</select>' 982 982 983 # BRStateChoiceField ######################################################### 984 >>> from django.contrib.localflavor.br.forms import BRStateChoiceField 985 >>> f = BRStateChoiceField() 986 >>> for s, n in f.widget.choices: 987 ... f.clean(s) 988 ... 989 u'AC' 990 u'AL' 991 u'AP' 992 u'AM' 993 u'BA' 994 u'CE' 995 u'DF' 996 u'ES' 997 u'GO' 998 u'MA' 999 u'MT' 1000 u'MS' 1001 u'MG' 1002 u'PA' 1003 u'PB' 1004 u'PR' 1005 u'PE' 1006 u'PI' 1007 u'RJ' 1008 u'RN' 1009 u'RS' 1010 u'RO' 1011 u'RR' 1012 u'SC' 1013 u'SP' 1014 u'SE' 1015 u'TO' 1016 >>> f.clean('') 1017 Traceback (most recent call last): 1018 ... 1019 ValidationError: [u'This field is required.'] 1020 >>> f.clean('pr') 1021 Traceback (most recent call last): 1022 ... 1023 ValidationError: [u'Select a valid brazilian state. That state is not one of the available states.'] 1024 983 1025 # DEZipCodeField ############################################################## 984 1026 985 1027 >>> from django.contrib.localflavor.de.forms import DEZipCodeField