Ticket #16497: mx_localflavors.diff
File mx_localflavors.diff, 26.2 KB (added by , 13 years ago) |
---|
-
AUTHORS
diff --git a/AUTHORS b/AUTHORS index 31a3300..d3a1e38 100644
a b answer newbie questions, and generally made Django that much better: 540 540 Gasper Zejn <zejn@kiberpipa.org> 541 541 Jarek Zgoda <jarek.zgoda@gmail.com> 542 542 Cheng Zhang 543 Gerardo Orozco <gerardo.orozco.mosqueda@gmail.com> 544 Andrés Torres Marroquín <andres.torres.marroquin@gmail.com> 543 545 544 546 A big THANK YOU goes to: 545 547 -
django/contrib/localflavor/mx/forms.py
diff --git a/django/contrib/localflavor/mx/forms.py b/django/contrib/localflavor/mx/forms.py index 9581937..ee1530b 100644
a b 1 # -*- coding: utf-8 -*- 1 2 """ 2 3 Mexican-specific form helpers. 3 4 """ 4 5 5 from django.forms.fields import Select 6 from django.forms import ValidationError 7 from django.forms.fields import Select, RegexField, CharField 8 from django.utils.translation import ugettext_lazy as _ 9 from django.core.validators import EMPTY_VALUES 10 from django.contrib.localflavor.mx.mx_states import STATE_CHOICES 11 import re 12 13 DATE_RE = r'\d{2}((01|03|05|07|08|10|12)(0[1-9]|[12]\d|3[01])|02(0[1-9]|[12]\d)|(04|06|09|11)(0[1-9]|[12]\d|30))' 14 15 """ 16 This is the list of inconvenient words according to the `Anexo IV` of the 17 document described in the next link: 18 http://www.sisi.org.mx/jspsi/documentos/2005/seguimiento/06101/0610100162005_065.doc 19 """ 20 21 RFC_INCONVENIENT_WORDS = [ 22 u'BUEI', u'BUEY', u'CACA', u'CACO', u'CAGA', u'CAGO', u'CAKA', u'CAKO', 23 u'COGE', u'COJA', u'COJE', u'COJI', u'COJO', u'CULO', u'FETO', u'GUEY', 24 u'JOTO', u'KACA', u'KACO', u'KAGA', u'KAGO', u'KOGE', u'KOJO', u'KAKA', 25 u'KULO', u'MAME', u'MAMO', u'MEAR', u'MEAS', u'MEON', u'MION', u'MOCO', 26 u'MULA', u'PEDA', u'PEDO', u'PENE', u'PUTA', u'PUTO', u'QULO', u'RATA', 27 u'RUIN' 28 ] 29 30 """ 31 This is the list of inconvenient words according to the `Anexo 2` of the 32 document described in the next link: 33 http://portal.veracruz.gob.mx/pls/portal/url/ITEM/444112558A57C6E0E040A8C02E00695C 34 """ 35 CURP_INCONVENIENT_WORDS = [ 36 u'BACA', u'BAKA', u'BUEI', u'BUEY', u'CACA', u'CACO', u'CAGA', u'CAGO', 37 u'CAKA', u'CAKO', u'COGE', u'COGI', u'COJA', u'COJE', u'COJI', u'COJO', 38 u'COLA', u'CULO', u'FALO', u'FETO', u'GETA', u'GUEI', u'GUEY', u'JETA', 39 u'JOTO', u'KACA', u'KACO', u'KAGA', u'KAGO', u'KAKA', u'KAKO', u'KOGE', 40 u'KOGI', u'KOJA', u'KOJE', u'KOJI', u'KOJO', u'KOLA', u'KULO', u'LILO', 41 u'LOCA', u'LOCO', u'LOKA', u'LOKO', u'MAME', u'MAMO', u'MEAR', u'MEAS', 42 u'MEON', u'MIAR', u'MION', u'MOCO', u'MOKO', u'MULA', u'MULO', u'NACA', 43 u'NACO', u'PEDA', u'PEDO', u'PENE', u'PIPI', u'PITO', u'POPO', u'PUTA', 44 u'PUTO', u'QULO', u'RATA', u'ROBA', u'ROBE', u'ROBO', u'RUIN', u'SENO', 45 u'TETA', u'VACA', u'VAGA', u'VAGO', u'VAKA', u'VUEI', u'VUEY', u'WUEI', 46 u'WUEY' 47 ] 6 48 7 49 class MXStateSelect(Select): 8 50 """ 9 51 A Select widget that uses a list of Mexican states as its choices. 10 52 """ 11 53 def __init__(self, attrs=None): 12 from mx_states import STATE_CHOICES13 54 super(MXStateSelect, self).__init__(attrs, choices=STATE_CHOICES) 14 55 56 class MXZipCodeField(RegexField): 57 """ 58 A form field that accepts a Mexican Zip Code. 59 60 More info about this: 61 http://en.wikipedia.org/wiki/List_of_postal_codes_in_Mexico 62 """ 63 default_error_messages = { 64 'invalid': _(u'Enter a valid zip code in the format XXXXX.'), 65 } 66 67 def __init__(self, *args, **kwargs): 68 zip_code_re = ur'^(0[1-9]|[1][0-6]|[2-9]\d)(\d{3})$' 69 super(MXZipCodeField, self).__init__(zip_code_re, *args, **kwargs) 70 71 class MXRFCField(RegexField): 72 """ 73 A form field that validates a Mexican *Registro Federal de Contribuyentes* for 74 either `Persona física` or `Persona moral`. 75 76 The Persona física RFC string is integrated by a juxtaposition of characters 77 following the next pattern: 78 79 ===== ====== =========================================== 80 Index Format Accepted Characters 81 ===== ====== =========================================== 82 1 X Any letter 83 2 X Any vowel 84 3-4 XX Any letter 85 5-10 YYMMDD Any valid date 86 11-12 XX Any letter or number between 0 and 9 87 13 X Any digit between 0 and 9 or the letter *A* 88 ===== ====== =========================================== 89 90 The Persona moral RFC string is integrated by a juxtaposition of characters 91 following the next pattern: 92 93 ===== ====== ============================================ 94 Index Format Accepted Characters 95 ===== ====== ============================================ 96 1-3 XXX Any letter including *&* and *Ñ* chars 97 4-9 YYMMDD Any valid date 98 10-11 XX Any letter or number between 0 and 9 99 12 X Any number between 0 and 9 or the letter *A* 100 ===== ====== ============================================ 101 102 More info about this: 103 http://es.wikipedia.org/wiki/Registro_Federal_de_Contribuyentes_(M%C3%A9xico) 104 """ 105 default_error_messages = { 106 'invalid': _(u'Enter a valid RFC.'), 107 'invalid_checksum': _(u'Invalid checksum for RFC.'), 108 } 109 110 def __init__(self, min_length=9, max_length=13, *args, **kwargs): 111 rfc_re = re.compile(ur'^([A-Z&Ññ]{3}|[A-Z][AEIOU][A-Z]{2})%s([A-Z0-9]{2}[0-9A])?$' % DATE_RE, 112 re.IGNORECASE) 113 super(MXRFCField, self).__init__(rfc_re, min_length=min_length, 114 max_length=max_length, *args, **kwargs) 115 116 def clean(self, value): 117 value = super(MXRFCField, self).clean(value) 118 if value in EMPTY_VALUES: 119 return u'' 120 value = value.upper() 121 if self._has_homoclave(value): 122 if not value[-1] == self._checksum(value[:-1]): 123 raise ValidationError(self.default_error_messages['invalid_checksum']) 124 if self._has_inconvenient_word(value): 125 raise ValidationError(self.default_error_messages['invalid']) 126 return value 127 128 def _has_homoclave(self, rfc): 129 """ 130 This check is done due to the existance of RFCs without a *homoclave* 131 since the current algorithm to calculate it had not been created for 132 the first RFCs ever in Mexico. 133 """ 134 rfc_without_homoclave_re = re.compile(ur'^[A-Z&Ññ]{3,4}%s$' % DATE_RE, 135 re.IGNORECASE) 136 return not rfc_without_homoclave_re.match(rfc) 137 138 def _checksum(self, rfc): 139 """ 140 More info about this procedure: 141 www.sisi.org.mx/jspsi/documentos/2005/seguimiento/06101/0610100162005_065.doc 142 """ 143 chars = u'0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ-Ñ' 144 if len(rfc) is 11: 145 rfc = '-' + rfc 146 147 sum_ = sum(i * chars.index(c) for i, c in zip(reversed(xrange(14)), rfc)) 148 checksum = 11 - sum_ % 11 149 150 if checksum == 10: 151 return u'A' 152 elif checksum == 11: 153 return u'0' 154 else: 155 return unicode(checksum) 156 157 def _has_inconvenient_word(self, rfc): 158 first_four = rfc[:4] 159 return first_four in RFC_INCONVENIENT_WORDS 160 161 class MXCURPField(RegexField): 162 """ 163 A field that validates a Mexican Clave Única de Registro de Población. 164 165 The CURP is integrated by a juxtaposition of characters following the next 166 pattern: 167 168 ===== ====== =================================================== 169 Index Format Accepted Characters 170 ===== ====== =================================================== 171 1 X Any letter 172 2 X Any vowel 173 3-4 XX Any letter 174 5-10 YYMMDD Any valid date 175 11 X Either `H` or `M`, depending on the person's gender 176 12-13 XX Any valid acronym for a state in Mexico 177 14-16 XXX Any consonant 178 17 X Any number between 0 and 9 or any letter 179 18 X Any number between 0 and 9 180 ===== ====== =================================================== 181 182 More info about this: 183 http://www.condusef.gob.mx/index.php/clave-unica-de-registro-de-poblacion-curp 184 """ 185 default_error_messages = { 186 'invalid': _('Enter a valid CURP.'), 187 'invalid_checksum': _(u'Invalid checksum for CURP.'), 188 } 189 190 def __init__(self, min_length=18, max_length=18, *args, **kwargs): 191 states_re = r'(AS|BC|BS|CC|CL|CM|CS|CH|DF|DG|GT|GR|HG|JC|MC|MN|MS|NT|NL|OC|PL|QT|QR|SP|SL|SR|TC|TS|TL|VZ|YN|ZS|NE)' 192 consonants_re = r'[B-DF-HJ-NP-TV-Z]' 193 curp_re = ur'^[A-Z][AEIOU][A-Z]{2}%s[HM]%s%s{3}[0-9A-Z]\d$' % (DATE_RE, states_re, 194 consonants_re) 195 curp_re = re.compile(curp_re, re.IGNORECASE) 196 super(MXCURPField, self).__init__(curp_re, min_length=min_length, 197 max_length=max_length, *args, **kwargs) 198 199 def clean(self, value): 200 value = super(MXCURPField, self).clean(value) 201 if value in EMPTY_VALUES: 202 return u'' 203 value = value.upper() 204 if value[-1] != self._checksum(value[:-1]): 205 raise ValidationError(self.default_error_messages['invalid_checksum']) 206 if self._has_inconvenient_word(value): 207 raise ValidationError(self.default_error_messages['invalid']) 208 return value 209 210 def _checksum(self, value): 211 chars = u'0123456789ABCDEFGHIJKLMN&OPQRSTUVWXYZ' 212 213 s = sum(i * chars.index(c) for i, c in zip(reversed(xrange(19)), value)) 214 checksum = 10 - s % 10 215 216 if checksum == 10: 217 return u'0' 218 return unicode(checksum) 219 220 def _has_inconvenient_word(self, curp): 221 first_four = curp[:4] 222 return first_four in CURP_INCONVENIENT_WORDS -
new file django/contrib/localflavor/mx/models.py
diff --git a/django/contrib/localflavor/mx/models.py b/django/contrib/localflavor/mx/models.py new file mode 100644 index 0000000..dd9a64b
- + 1 from django.utils.translation import ugettext_lazy as _ 2 from django.db.models.fields import CharField 3 from django.contrib.localflavor.mx.mx_states import STATE_CHOICES 4 5 class MXStateField(CharField): 6 """ 7 A model field that stores the three-letter Mexican state abbreviation in the 8 database. 9 """ 10 11 description = _("Mexico state (three uppercase letters)") 12 13 def __init__(self, *args, **kwargs): 14 kwargs['choices'] = STATE_CHOICES 15 kwargs['max_length'] = 3 16 super(MXStateField, self).__init__(*args, **kwargs) 17 18 class MXZipCodeField(CharField): 19 """ 20 A model field that forms represent as a forms.MXZipCodeField field and 21 stores the five-digit Mexican zip code. 22 """ 23 24 description = _("Mexico zip code") 25 26 def __init__(self, *args, **kwargs): 27 kwargs['max_length'] = 5 28 super(MXZipCodeField, self).__init__(*args, **kwargs) 29 30 def formfield(self, **kwargs): 31 from django.contrib.localflavor.mx.forms import MXZipCodeField as Field 32 defaults = {'form_class': Field} 33 defaults.update(kwargs) 34 return super(MXZipCodeField, self).formfield(**defaults) 35 36 class MXRFCField(CharField): 37 """ 38 A model field that forms represent as a forms.MXRFCField field and 39 stores the value of a valid Mexican RFC. 40 """ 41 42 description = _("Mexican RFC") 43 44 def __init__(self, *args, **kwargs): 45 kwargs['max_length'] = 13 46 super(MXRFCField, self).__init__(*args, **kwargs) 47 48 def formfield(self, **kwargs): 49 from django.contrib.localflavor.mx.forms import MXRFCField as Field 50 defaults = {'form_class': Field} 51 defaults.update(kwargs) 52 return super(MXRFCField, self).formfield(**defaults) 53 54 class MXCURPField(CharField): 55 """ 56 A model field that forms represent as a forms.MXCURPField field and 57 stores the value of a valid Mexican CURP. 58 """ 59 60 description = _("Mexican CURP") 61 62 def __init__(self, *args, **kwargs): 63 kwargs['max_length'] = 18 64 super(MXCURPField, self).__init__(*args, **kwargs) 65 66 def formfield(self, **kwargs): 67 from django.contrib.localflavor.mx.forms import MXCURPField as Field 68 defaults = {'form_class': Field} 69 defaults.update(kwargs) 70 return super(MXCURPField, self).formfield(**defaults) 71 No newline at end of file -
django/contrib/localflavor/mx/mx_states.py
diff --git a/django/contrib/localflavor/mx/mx_states.py b/django/contrib/localflavor/mx/mx_states.py index eed1700..8632888 100644
a b when explicitly needed. 8 8 9 9 from django.utils.translation import ugettext_lazy as _ 10 10 11 STATE_CHOICES = ( 11 # All 31 states, plus the `Distrito Federal`. 12 MX_STATES = ( 12 13 ('AGU', _(u'Aguascalientes')), 13 14 ('BCN', _(u'Baja California')), 14 15 ('BCS', _(u'Baja California Sur')), -
docs/ref/contrib/localflavor.txt
diff --git a/docs/ref/contrib/localflavor.txt b/docs/ref/contrib/localflavor.txt index 60539e9..f4bc892 100644
a b Macedonia (``mk``) 774 774 Mexico (``mx``) 775 775 =============== 776 776 777 .. class:: mx.forms.MXZipCodeField 778 779 A form field that accepts a Mexican Zip Code. 780 781 More info about this: List of postal codes in Mexico (zipcodes_) 782 783 .. _zipcodes: http://en.wikipedia.org/wiki/List_of_postal_codes_in_Mexico 784 785 .. class:: mx.forms.MXRFCField 786 787 A form field that validates a Mexican *Registro Federal de Contribuyentes* for 788 either **Persona física** or **Persona moral**. This field accepts RFC strings 789 whether or not it contains a *homoclave*. 790 791 More info about this: Registro Federal de Contribuyentes (rfc_) 792 793 .. _rfc: http://es.wikipedia.org/wiki/Registro_Federal_de_Contribuyentes_(M%C3%A9xico) 794 795 .. class:: mx.forms.MXCURPField 796 797 A field that validates a Mexican *Clave Única de Registro de Población*. 798 799 More info about this: Clave Unica de Registro de Poblacion (curp_) 800 801 .. _curp: http://www.condusef.gob.mx/index.php/clave-unica-de-registro-de-poblacion-curp 802 777 803 .. class:: mx.forms.MXStateSelect 778 804 779 805 A ``Select`` widget that uses a list of Mexican states as its choices. 780 806 807 .. class:: mx.models.MXStateField 808 809 A model field that stores the three-letter Mexican state abbreviation in the 810 database. 811 812 .. class:: mx.models.MXZipCodeField 813 814 A model field that forms represent as a ``forms.MXZipCodeField`` field and 815 stores the five-digit Mexican zip code. 816 817 .. class:: mx.models.MXRFCField 818 819 A model field that forms represent as a ``forms.MXRFCField`` field and 820 stores the value of a valid Mexican RFC. 821 822 .. class:: mx.models.MXCURPField 823 824 A model field that forms represent as a ``forms.MXCURPField`` field and 825 stores the value of a valid Mexican CURP. 826 827 Additionally, a choice tuple is provided in ``django.contrib.localflavor.mx.mx_states``, 828 allowing customized model and form fields, and form presentations, for subsets of 829 Mexican states abbreviations: 830 831 .. data:: mx.mx_states.MX_STATES 832 833 A tuple of choices of the states abbreviations for all 31 Mexican states, 834 plus the `Distrito Federal`. 835 781 836 Norway (``no``) 782 837 =============== 783 838 -
new file tests/regressiontests/forms/localflavor/mx.py
diff --git a/tests/regressiontests/forms/localflavor/mx.py b/tests/regressiontests/forms/localflavor/mx.py new file mode 100644 index 0000000..1ffc11c
- + 1 # -*- coding: utf-8 -*- 2 from django.contrib.localflavor.mx.forms import (MXZipCodeField, MXRFCField, 3 MXStateSelect, MXCURPField) 4 5 from utils import LocalFlavorTestCase 6 7 8 class MXLocalFlavorTests(LocalFlavorTestCase): 9 def test_MXStateSelect(self): 10 f = MXStateSelect() 11 out = u'''<select name="state"> 12 <option value="AGU">Aguascalientes</option> 13 <option value="BCN">Baja California</option> 14 <option value="BCS">Baja California Sur</option> 15 <option value="CAM">Campeche</option> 16 <option value="CHH">Chihuahua</option> 17 <option value="CHP">Chiapas</option> 18 <option value="COA">Coahuila</option> 19 <option value="COL">Colima</option> 20 <option value="DIF">Distrito Federal</option> 21 <option value="DUR">Durango</option> 22 <option value="GRO">Guerrero</option> 23 <option value="GUA">Guanajuato</option> 24 <option value="HID">Hidalgo</option> 25 <option value="JAL">Jalisco</option> 26 <option value="MEX">Estado de México</option> 27 <option value="MIC" selected="selected">Michoacán</option> 28 <option value="MOR">Morelos</option> 29 <option value="NAY">Nayarit</option> 30 <option value="NLE">Nuevo León</option> 31 <option value="OAX">Oaxaca</option> 32 <option value="PUE">Puebla</option> 33 <option value="QUE">Querétaro</option> 34 <option value="ROO">Quintana Roo</option> 35 <option value="SIN">Sinaloa</option> 36 <option value="SLP">San Luis Potosí</option> 37 <option value="SON">Sonora</option> 38 <option value="TAB">Tabasco</option> 39 <option value="TAM">Tamaulipas</option> 40 <option value="TLA">Tlaxcala</option> 41 <option value="VER">Veracruz</option> 42 <option value="YUC">Yucatán</option> 43 <option value="ZAC">Zacatecas</option> 44 </select>''' 45 self.assertEqual(f.render('state', 'MIC'), out) 46 47 def test_MXZipCodeField(self): 48 error_format = [u'Enter a valid zip code in the format XXXXX.'] 49 valid = { 50 '58120': u'58120', 51 '58502': u'58502', 52 '59310': u'59310', 53 '99999': u'99999', 54 } 55 invalid = { 56 '17000': error_format, 57 '18000': error_format, 58 '19000': error_format, 59 '00000': error_format, 60 } 61 self.assertFieldOutput(MXZipCodeField, valid, invalid) 62 63 def test_MXRFCField(self): 64 error_format = [u'Enter a valid RFC.'] 65 error_checksum = [u'Invalid checksum for RFC.'] 66 valid = { 67 'MoFN641205eX5': u'MOFN641205EX5', 68 'ICa060120873': u'ICA060120873', 69 'eUcG751104rT0': u'EUCG751104RT0', 70 'GME08100195A': u'GME08100195A', 71 'AA&060524KX5': u'AA&060524KX5', 72 'CAÑ0708045P7': u'CAÑ0708045P7', 73 'aaa000101aa9': u'AAA000101AA9', 74 } 75 invalid = { 76 'MED0000000XA': error_format, 77 '0000000000XA': error_format, 78 'AAA000000AA6': error_format, 79 # Dates 80 'XXX880002XXX': error_format, 81 'XXX880200XXX': error_format, 82 'XXX880132XXX': error_format, 83 'XXX880230XXX': error_format, 84 'XXX880431XXX': error_format, 85 # Incorrect checksum 86 'MOGR650524E73': error_checksum, 87 'HVA7810058F1': error_checksum, 88 'MoFN641205eX2': error_checksum, 89 'ICa060120871': error_checksum, 90 'eUcG751104rT7': error_checksum, 91 'GME081001955': error_checksum, 92 'AA&060524KX9': error_checksum, 93 'CAÑ0708045P2': error_checksum, 94 } 95 self.assertFieldOutput(MXRFCField, valid, invalid) 96 97 def test_MXCURPField(self): 98 error_format = [u'Enter a valid CURP.'] 99 error_checksum = [u'Invalid checksum for CURP.'] 100 valid = { 101 'AaMG890608HDFLJL00': u'AAMG890608HDFLJL00', 102 'BAAd890419HMNRRV07': u'BAAD890419HMNRRV07', 103 'VIAA900930MMNClL08': u'VIAA900930MMNCLL08', 104 'HEGR891009HMNRRD09': u'HEGR891009HMNRRD09', 105 'MARR890512HMNRMN09': u'MARR890512HMNRMN09', 106 'MESJ890928HMNZNS00': u'MESJ890928HMNZNS00', 107 'BAAA890317HDFRLL03': u'BAAA890317HDFRLL03', 108 'TOMA880125HMNRRNO2': u'TOMA880125HMNRRNO2', 109 'OOMG890727HMNRSR06': u'OOMG890727HMNRSR06', 110 'AAAA000101HDFCCC09': u'AAAA000101HDFCCC09', 111 } 112 invalid = { 113 'AAAA000000HDFCCC09': error_format, 114 'AAAA000000HDFAAA03': error_format, 115 'AAAA000000HXXCCC08': error_format, 116 'AAAA000000XMNCCC02': error_format, 117 'HEGR891009HMNRRD0A': error_format, 118 'MARR890512HMNRMN0A': error_format, 119 'AaMG890608HDFLJL01': error_checksum, 120 'BAAd890419HMNRRV08': error_checksum, 121 'VIAA900930MMNClL09': error_checksum, 122 'MESJ890928HMNZNS01': error_checksum, 123 'BAAA890317HDFRLL04': error_checksum, 124 'TOMA880125HMNRRNO3': error_checksum, 125 'OOMG890727HMNRSR07': error_checksum, 126 } 127 self.assertFieldOutput(MXCURPField, valid, invalid) -
tests/regressiontests/forms/localflavortests.py
diff --git a/tests/regressiontests/forms/localflavortests.py b/tests/regressiontests/forms/localflavortests.py index 7f29fea..09afad8 100644
a b from localflavor.it import ITLocalFlavorTests 25 25 from localflavor.jp import JPLocalFlavorTests 26 26 from localflavor.kw import KWLocalFlavorTests 27 27 from localflavor.mk import MKLocalFlavorTests 28 from localflavor.mx import MXLocalFlavorTests 28 29 from localflavor.nl import NLLocalFlavorTests 29 30 from localflavor.pl import PLLocalFlavorTests 30 31 from localflavor.pt import PTLocalFlavorTests -
tests/regressiontests/forms/tests/__init__.py
diff --git a/tests/regressiontests/forms/tests/__init__.py b/tests/regressiontests/forms/tests/__init__.py index 6715451..fa947f9 100644
a b from regressiontests.forms.localflavortests import ( 38 38 JPLocalFlavorTests, 39 39 KWLocalFlavorTests, 40 40 MKLocalFlavorTests, 41 MXLocalFlavorTests, 41 42 NLLocalFlavorTests, 42 43 PLLocalFlavorTests, 43 44 PTLocalFlavorTests, -
new file tests/regressiontests/localflavor/mx/forms.py
diff --git a/tests/regressiontests/localflavor/mx/__init__.py b/tests/regressiontests/localflavor/mx/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/regressiontests/localflavor/mx/forms.py b/tests/regressiontests/localflavor/mx/forms.py new file mode 100644 index 0000000..8a45781
- + 1 from django.forms import ModelForm 2 from models import MXPersonProfile 3 4 class MXPersonProfileForm(ModelForm): 5 """docstring for MXPersonProfileForm""" 6 class Meta: 7 model = MXPersonProfile -
new file tests/regressiontests/localflavor/mx/models.py
diff --git a/tests/regressiontests/localflavor/mx/models.py b/tests/regressiontests/localflavor/mx/models.py new file mode 100644 index 0000000..81a5018
- + 1 from django.db import models 2 from django.contrib.localflavor.mx.models import (MXStateField, 3 MXRFCField, MXCURPField, MXZipCodeField) 4 5 # When creating models you need to remember to add a app_label as 6 # 'localflavor', so your model can be found 7 8 class MXPersonProfile(models.Model): 9 state = MXStateField() 10 rfc = MXRFCField() 11 curp = MXCURPField() 12 zip_code = MXZipCodeField() 13 class Meta: 14 app_label = 'localflavor' -
new file tests/regressiontests/localflavor/mx/tests.py
diff --git a/tests/regressiontests/localflavor/mx/tests.py b/tests/regressiontests/localflavor/mx/tests.py new file mode 100644 index 0000000..40da38a
- + 1 # -*- coding: utf-8 -*- 2 from django.test import TestCase 3 from forms import MXPersonProfileForm 4 5 class MXLocalFlavorTests(TestCase): 6 def setUp(self): 7 self.form = MXPersonProfileForm({ 8 'state': 'MIC', 9 'rfc': 'toma880125kv3', 10 'curp': 'toma880125hmnrrn02', 11 'zip_code': '58120', 12 }) 13 14 def test_get_display_methods(self): 15 """Test that the get_*_display() methods are added to the model instances.""" 16 place = self.form.save() 17 self.assertEqual(place.get_state_display(), u'Michoacán') 18 19 def test_errors(self): 20 """Test that required MXFields throw appropriate errors.""" 21 form = MXPersonProfileForm({ 22 'state': 'Invalid state', 23 'rfc': 'invalid rfc', 24 'curp': 'invalid curp', 25 'zip_code': 'xxx', 26 }) 27 self.assertFalse(form.is_valid()) 28 self.assertEqual(form.errors['state'], [u'Select a valid choice. Invalid state is not one of the available choices.']) 29 self.assertEqual(form.errors['rfc'], [u'Enter a valid RFC.']) 30 self.assertEqual(form.errors['curp'], [u'Ensure this value has at least 18 characters (it has 12).', u'Enter a valid CURP.']) 31 self.assertEqual(form.errors['zip_code'], [u'Enter a valid zip code in the format XXXXX.']) 32 33 def test_field_blank_option(self): 34 """Test that the empty option is there.""" 35 state_select_html = """\ 36 <select name="state" id="id_state"> 37 <option value="">---------</option> 38 <option value="AGU">Aguascalientes</option> 39 <option value="BCN">Baja California</option> 40 <option value="BCS">Baja California Sur</option> 41 <option value="CAM">Campeche</option> 42 <option value="CHH">Chihuahua</option> 43 <option value="CHP">Chiapas</option> 44 <option value="COA">Coahuila</option> 45 <option value="COL">Colima</option> 46 <option value="DIF">Distrito Federal</option> 47 <option value="DUR">Durango</option> 48 <option value="GRO">Guerrero</option> 49 <option value="GUA">Guanajuato</option> 50 <option value="HID">Hidalgo</option> 51 <option value="JAL">Jalisco</option> 52 <option value="MEX">Estado de México</option> 53 <option value="MIC" selected="selected">Michoacán</option> 54 <option value="MOR">Morelos</option> 55 <option value="NAY">Nayarit</option> 56 <option value="NLE">Nuevo León</option> 57 <option value="OAX">Oaxaca</option> 58 <option value="PUE">Puebla</option> 59 <option value="QUE">Querétaro</option> 60 <option value="ROO">Quintana Roo</option> 61 <option value="SIN">Sinaloa</option> 62 <option value="SLP">San Luis Potosí</option> 63 <option value="SON">Sonora</option> 64 <option value="TAB">Tabasco</option> 65 <option value="TAM">Tamaulipas</option> 66 <option value="TLA">Tlaxcala</option> 67 <option value="VER">Veracruz</option> 68 <option value="YUC">Yucatán</option> 69 <option value="ZAC">Zacatecas</option> 70 </select>""" 71 self.assertEqual(str(self.form['state']), state_select_html) -
tests/regressiontests/localflavor/tests.py
diff --git a/tests/regressiontests/localflavor/tests.py b/tests/regressiontests/localflavor/tests.py index 6a15d46..95a5f99 100644
a b 1 1 from au.tests import * 2 2 from mk.tests import * 3 from mx.tests import * 3 4 from us.tests import * 4 5