Django

Code

root/django/trunk/django/contrib/localflavor/br/forms.py

Revision 7971, 5.7 kB (checked in by jacob, 2 months ago)

Fixed #7741: django.newforms is now django.forms. This is obviously a backwards-incompatible change. There's a warning upon import of django.newforms itself, but deeper imports will raise errors.

  • Property svn:eol-style set to native
Line 
1 # -*- coding: utf-8 -*-
2 """
3 BR-specific Form helpers
4 """
5
6 from django.forms import ValidationError
7 from django.forms.fields import Field, RegexField, CharField, Select, EMPTY_VALUES
8 from django.utils.encoding import smart_unicode
9 from django.utils.translation import ugettext_lazy as _
10 import re
11
12 try:
13     set
14 except NameError:
15     from sets import Set as set     # For Python 2.3
16
17 phone_digits_re = re.compile(r'^(\d{2})[-\.]?(\d{4})[-\.]?(\d{4})$')
18
19 class BRZipCodeField(RegexField):
20     default_error_messages = {
21         'invalid': _('Enter a zip code in the format XXXXX-XXX.'),
22     }
23
24     def __init__(self, *args, **kwargs):
25         super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$',
26             max_length=None, min_length=None, *args, **kwargs)
27
28 class BRPhoneNumberField(Field):
29     default_error_messages = {
30         'invalid': _('Phone numbers must be in XX-XXXX-XXXX format.'),
31     }
32
33     def clean(self, value):
34         super(BRPhoneNumberField, self).clean(value)
35         if value in EMPTY_VALUES:
36             return u''
37         value = re.sub('(\(|\)|\s+)', '', smart_unicode(value))
38         m = phone_digits_re.search(value)
39         if m:
40             return u'%s-%s-%s' % (m.group(1), m.group(2), m.group(3))
41         raise ValidationError(self.error_messages['invalid'])
42
43 class BRStateSelect(Select):
44     """
45     A Select widget that uses a list of Brazilian states/territories
46     as its choices.
47     """
48     def __init__(self, attrs=None):
49         from br_states import STATE_CHOICES
50         super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
51
52 class BRStateChoiceField(Field):
53     """
54     A choice field that uses a list of Brazilian states as its choices.
55     """
56     widget = Select
57     default_error_messages = {
58         'invalid': _(u'Select a valid brazilian state. That state is not one of the available states.'),
59     }
60
61     def __init__(self, required=True, widget=None, label=None,
62                  initial=None, help_text=None):
63         super(BRStateChoiceField, self).__init__(required, widget, label,
64                                                  initial, help_text)
65         from br_states import STATE_CHOICES
66         self.widget.choices = STATE_CHOICES
67
68     def clean(self, value):
69         value = super(BRStateChoiceField, self).clean(value)
70         if value in EMPTY_VALUES:
71             value = u''
72         value = smart_unicode(value)
73         if value == u'':
74             return value
75         valid_values = set([smart_unicode(k) for k, v in self.widget.choices])
76         if value not in valid_values:
77             raise ValidationError(self.error_messages['invalid'])
78         return value
79
80 def DV_maker(v):
81     if v >= 2:
82         return 11 - v
83     return 0
84
85 class BRCPFField(CharField):
86     """
87     This field validate a CPF number or a CPF string. A CPF number is
88     compounded by XXX.XXX.XXX-VD. The two last digits are check digits.
89
90     More information:
91     http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas
92     """
93     default_error_messages = {
94         'invalid': _("Invalid CPF number."),
95         'max_digits': _("This field requires at most 11 digits or 14 characters."),
96         'digits_only': _("This field requires only numbers."),
97     }
98
99     def __init__(self, *args, **kwargs):
100         super(BRCPFField, self).__init__(max_length=14, min_length=11, *args, **kwargs)
101
102     def clean(self, value):
103         """
104         Value can be either a string in the format XXX.XXX.XXX-XX or an
105         11-digit number.
106         """
107         value = super(BRCPFField, self).clean(value)
108         if value in EMPTY_VALUES:
109             return u''
110         orig_value = value[:]
111         if not value.isdigit():
112             value = re.sub("[-\.]", "", value)
113         try:
114             int(value)
115         except ValueError:
116             raise ValidationError(self.error_messages['digits_only'])
117         if len(value) != 11:
118             raise ValidationError(self.error_messages['max_digits'])
119         orig_dv = value[-2:]
120
121         new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(10, 1, -1))])
122         new_1dv = DV_maker(new_1dv % 11)
123         value = value[:-2] + str(new_1dv) + value[-1]
124         new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(range(11, 1, -1))])
125         new_2dv = DV_maker(new_2dv % 11)
126         value = value[:-1] + str(new_2dv)
127         if value[-2:] != orig_dv:
128             raise ValidationError(self.error_messages['invalid'])
129
130         return orig_value
131
132 class BRCNPJField(Field):
133     default_error_messages = {
134         'invalid': _("Invalid CNPJ number."),
135         'digits_only': _("This field requires only numbers."),
136         'max_digits': _("This field requires at least 14 digits"),
137     }
138
139     def clean(self, value):
140         """
141         Value can be either a string in the format XX.XXX.XXX/XXXX-XX or a
142         group of 14 characters.
143         """
144         value = super(BRCNPJField, self).clean(value)
145         if value in EMPTY_VALUES:
146             return u''
147         orig_value = value[:]
148         if not value.isdigit():
149             value = re.sub("[-/\.]", "", value)
150         try:
151             int(value)
152         except ValueError:
153             raise ValidationError(self.error_messages['digits_only'])
154         if len(value) != 14:
155             raise ValidationError(self.error_messages['max_digits'])
156         orig_dv = value[-2:]
157
158         new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(5, 1, -1) + range(9, 1, -1))])
159         new_1dv = DV_maker(new_1dv % 11)
160         value = value[:-2] + str(new_1dv) + value[-1]
161         new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(range(6, 1, -1) + range(9, 1, -1))])
162         new_2dv = DV_maker(new_2dv % 11)
163         value = value[:-1] + str(new_2dv)
164         if value[-2:] != orig_dv:
165             raise ValidationError(self.error_messages['invalid'])
166
167         return orig_value
Note: See TracBrowser for help on using the browser.