Ticket #4964: brlocalflavor.diff

File brlocalflavor.diff, 11.4 KB (added by wiliamsouza83@…, 17 years ago)
  • django/contrib/localflavor/br/forms.py

     
    11# -*- coding: utf-8 -*-
    22"""
    33BR-specific Form helpers
     4
     5Usage:
     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()
     31True
    432"""
    533
     34import re
     35from django.utils.translation import ugettext
     36from django.utils.encoding import smart_unicode
    637from 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
     38from django.newforms.fields import (Field, RegexField,
     39                                    CharField, Select,
     40                                    EMPTY_VALUES)
    1141
    1242phone_digits_re = re.compile(r'^(\d{2})[-\.]?(\d{4})[-\.]?(\d{4})$')
    1343
    1444class BRZipCodeField(RegexField):
     45    """
     46    A field that checks brazilian zipcode format.
     47    """
    1548    def __init__(self, *args, **kwargs):
     49        error = ugettext('Enter a zip code in the format XXXXX-XXX.')
    1650        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)
    2056
    2157class BRPhoneNumberField(Field):
     58    """
     59    A field that checks brazilian phone number format.
     60    """
    2261    def clean(self, value):
    2362        super(BRPhoneNumberField, self).clean(value)
    2463        if value in EMPTY_VALUES:
     
    2766        m = phone_digits_re.search(value)
    2867        if m:
    2968            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.'))
    3171
    32 class BRStateSelect(Select):
     72class BRStateChoiceField(Field):
    3373    """
    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.
    3675    """
    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)
    3882        from br_states import STATE_CHOICES
    39         super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
     83        self.widget.choices = STATE_CHOICES
    4084
     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
    4198
     99
     100
    42101def DV_maker(v):
    43102    if v >= 2:
    44103        return 11 - v
     
    46105
    47106class BRCPFField(CharField):
    48107    """
    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.
    51113
    52114    More information:
    53115    http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas
    54116    """
    55117    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)
    57120
    58121    def clean(self, value):
    59         """
    60         Value can be either a string in the format XXX.XXX.XXX-XX or an
    61         11-digit number.
    62         """
    63122        value = super(BRCPFField, self).clean(value)
    64123        if value in EMPTY_VALUES:
    65124            return u''
    66125        orig_value = value[:]
    67126        if not value.isdigit():
    68             value = re.sub("[-\.]", "", value)
     127            value = re.sub('[-\.]', '', value)
    69128        try:
    70129            int(value)
    71130        except ValueError:
    72             raise ValidationError(ugettext("This field requires only numbers."))
     131            raise ValidationError(ugettext('This field requires'
     132                                           ' only numbers.'))
    73133        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.'))
    75136        orig_dv = value[-2:]
    76137
    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))])
    78140        new_1dv = DV_maker(new_1dv % 11)
    79141        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))])
    81144        new_2dv = DV_maker(new_2dv % 11)
    82145        value = value[:-1] + str(new_2dv)
    83146        if value[-2:] != orig_dv:
    84             raise ValidationError(ugettext("Invalid CPF number."))
     147            raise ValidationError(ugettext('Invalid CPF number.'))
    85148
    86149        return orig_value
    87150
    88151class 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    """
    89158    def clean(self, value):
    90         """
    91         Value can be either a string in the format XX.XXX.XXX/XXXX-XX or a
    92         group of 14 characters.
    93         """
    94159        value = super(BRCNPJField, self).clean(value)
    95160        if value in EMPTY_VALUES:
    96161            return u''
    97162        orig_value = value[:]
    98163        if not value.isdigit():
    99             value = re.sub("[-/\.]", "", value)
     164            value = re.sub('[-/\.]', '', value)
    100165        try:
    101166            int(value)
    102167        except ValueError:
    103             raise ValidationError("This field requires only numbers.")
     168            raise ValidationError('This field requires only numbers.')
    104169        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'))
    107172        orig_dv = value[-2:]
    108173
    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))])
    110177        new_1dv = DV_maker(new_1dv % 11)
    111178        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))])
    113182        new_2dv = DV_maker(new_2dv % 11)
    114183        value = value[:-1] + str(new_2dv)
    115184        if value[-2:] != orig_dv:
    116             raise ValidationError(ugettext("Invalid CNPJ number."))
     185            raise ValidationError(ugettext('Invalid CNPJ number.'))
    117186
    118187        return orig_value
    119188
     189# Widgets
     190class 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

     
    980980>>> w.render('states', 'PR')
    981981u'<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>'
    982982
     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...
     989u'AC'
     990u'AL'
     991u'AP'
     992u'AM'
     993u'BA'
     994u'CE'
     995u'DF'
     996u'ES'
     997u'GO'
     998u'MA'
     999u'MT'
     1000u'MS'
     1001u'MG'
     1002u'PA'
     1003u'PB'
     1004u'PR'
     1005u'PE'
     1006u'PI'
     1007u'RJ'
     1008u'RN'
     1009u'RS'
     1010u'RO'
     1011u'RR'
     1012u'SC'
     1013u'SP'
     1014u'SE'
     1015u'TO'
     1016>>> f.clean('')
     1017Traceback (most recent call last):
     1018...
     1019ValidationError: [u'This field is required.']
     1020>>> f.clean('pr')
     1021Traceback (most recent call last):
     1022...
     1023ValidationError: [u'Select a valid brazilian state. That state is not one of the available states.']
     1024
    9831025# DEZipCodeField ##############################################################
    9841026
    9851027>>> from django.contrib.localflavor.de.forms import DEZipCodeField
Back to Top