Skip to content

Commit 3825bb2

Browse files
committed
Fixed #10736 - Added Uruguayan (uy) localflavor. Thanks to Gonzalo Saavedra for providing the patch.
git-svn-id: http://code.djangoproject.com/svn/django/trunk@12041 bcc190cf-cafb-0310-a4f2-bffc1f526a37
1 parent f2d0ae9 commit 3825bb2

File tree

8 files changed

+158
-0
lines changed

8 files changed

+158
-0
lines changed

AUTHORS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ answer newbie questions, and generally made Django that much better:
383383
384384
Oliver Rutherfurd <http://rutherfurd.net/>
385385
ryankanno
386+
Gonzalo Saavedra <[email protected]>
386387
Manuel Saelices <[email protected]>
387388
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
388389
Vinay Sajip <[email protected]>

django/contrib/localflavor/uy/__init__.py

Whitespace-only changes.
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# -*- coding: utf-8 -*-
2+
"""
3+
UY-specific form helpers.
4+
"""
5+
import re
6+
7+
from django.forms.fields import Select, RegexField, EMPTY_VALUES
8+
from django.forms import ValidationError
9+
from django.utils.translation import ugettext_lazy as _
10+
from django.contrib.localflavor.uy.util import get_validation_digit
11+
12+
13+
class UYDepartamentSelect(Select):
14+
"""
15+
A Select widget that uses a list of Uruguayan departaments as its choices.
16+
"""
17+
def __init__(self, attrs=None):
18+
from uy_departaments import DEPARTAMENT_CHOICES
19+
super(UYDepartamentSelect, self).__init__(attrs, choices=DEPARTAMENT_CHOICES)
20+
21+
22+
class UYCIField(RegexField):
23+
"""
24+
A field that validates Uruguayan 'Cedula de identidad' (CI) numbers.
25+
"""
26+
default_error_messages = {
27+
'invalid': _("Enter a valid CI number in X.XXX.XXX-X,"
28+
"XXXXXXX-X or XXXXXXXX format."),
29+
'invalid_validation_digit': _("Enter a valid CI number."),
30+
}
31+
32+
def __init__(self, *args, **kwargs):
33+
super(UYCIField, self).__init__(r'(?P<num>(\d{6,7}|(\d\.)?\d{3}\.\d{3}))-?(?P<val>\d)',
34+
*args, **kwargs)
35+
36+
def clean(self, value):
37+
"""
38+
Validates format and validation digit.
39+
40+
The official format is [X.]XXX.XXX-X but usually dots and/or slash are
41+
omitted so, when validating, those characters are ignored if found in
42+
the correct place. The three typically used formats are supported:
43+
[X]XXXXXXX, [X]XXXXXX-X and [X.]XXX.XXX-X.
44+
"""
45+
46+
value = super(UYCIField, self).clean(value)
47+
if value in EMPTY_VALUES:
48+
return u''
49+
match = self.regex.match(value)
50+
if not match:
51+
raise ValidationError(self.error_messages['invalid'])
52+
53+
number = int(match.group('num').replace('.', ''))
54+
validation_digit = int(match.group('val'))
55+
56+
if not validation_digit == get_validation_digit(number):
57+
raise ValidationError(self.error_messages['invalid_validation_digit'])
58+
59+
return value

django/contrib/localflavor/uy/util.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# -*- coding: utf-8 -*-
2+
3+
def get_validation_digit(number):
4+
""" Calculates the validation digit for the given number. """
5+
sum = 0
6+
dvs = [4, 3, 6, 7, 8, 9, 2]
7+
number = str(number)
8+
9+
for i in range(0, len(number)):
10+
sum = (int(number[-1 - i]) * dvs[i] + sum) % 10
11+
12+
return (10-sum) % 10
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# -*- coding: utf-8 -*-
2+
"""A list of Urguayan departaments as `choices` in a formfield."""
3+
4+
DEPARTAMENT_CHOICES = (
5+
('G', u'Artigas'),
6+
('A', u'Canelones'),
7+
('E', u'Cerro Largo'),
8+
('L', u'Colonia'),
9+
('Q', u'Durazno'),
10+
('N', u'Flores'),
11+
('O', u'Florida'),
12+
('P', u'Lavalleja'),
13+
('B', u'Maldonado'),
14+
('S', u'Montevideo'),
15+
('I', u'Paysandú'),
16+
('J', u'Río Negro'),
17+
('F', u'Rivera'),
18+
('C', u'Rocha'),
19+
('H', u'Salto'),
20+
('M', u'San José'),
21+
('K', u'Soriano'),
22+
('R', u'Tacuarembó'),
23+
('D', u'Treinta y Tres'),
24+
)

docs/ref/contrib/localflavor.txt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ Countries currently supported by :mod:`~django.contrib.localflavor` are:
6565
* Switzerland_
6666
* `United Kingdom`_
6767
* `United States of America`_
68+
* Uruguay_
6869

6970
The ``django.contrib.localflavor`` package also includes a ``generic`` subpackage,
7071
containing useful code that is not specific to one particular country or culture.
@@ -106,6 +107,7 @@ Here's an example of how to use them::
106107
.. _Switzerland: `Switzerland (ch)`_
107108
.. _United Kingdom: `United Kingdom (uk)`_
108109
.. _United States of America: `United States of America (us)`_
110+
.. _Uruguay: `Uruguay (uy)`_
109111

110112
Adding flavors
111113
==============
@@ -738,3 +740,15 @@ United States of America (``us``)
738740

739741
A model field that forms represent as a ``forms.USStateField`` field and
740742
stores the two-letter U.S. state abbreviation in the database.
743+
744+
Uruguay (``uy``)
745+
================
746+
747+
.. class:: uy.forms.UYCIField
748+
749+
A field that validates Uruguayan 'Cedula de identidad' (CI) numbers.
750+
751+
.. class:: uy.forms.UYDepartamentSelect
752+
753+
A ``Select`` widget that uses a list of Uruguayan departaments as its
754+
choices.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
# -*- coding: utf-8 -*-
2+
# Tests for the contrib/localflavor/ UY form fields.
3+
4+
tests = r"""
5+
# UYDepartamentSelect #########################################################
6+
7+
>>> from django.contrib.localflavor.uy.forms import UYDepartamentSelect
8+
>>> f = UYDepartamentSelect()
9+
>>> f.render('departamentos', 'S')
10+
u'<select name="departamentos">\n<option value="G">Artigas</option>\n<option value="A">Canelones</option>\n<option value="E">Cerro Largo</option>\n<option value="L">Colonia</option>\n<option value="Q">Durazno</option>\n<option value="N">Flores</option>\n<option value="O">Florida</option>\n<option value="P">Lavalleja</option>\n<option value="B">Maldonado</option>\n<option value="S" selected="selected">Montevideo</option>\n<option value="I">Paysand\xfa</option>\n<option value="J">R\xedo Negro</option>\n<option value="F">Rivera</option>\n<option value="C">Rocha</option>\n<option value="H">Salto</option>\n<option value="M">San Jos\xe9</option>\n<option value="K">Soriano</option>\n<option value="R">Tacuaremb\xf3</option>\n<option value="D">Treinta y Tres</option>\n</select>'
11+
12+
# UYCIField ###################################################################
13+
14+
>>> from django.contrib.localflavor.uy.util import get_validation_digit
15+
>>> get_validation_digit(409805) == 3
16+
True
17+
>>> get_validation_digit(1005411) == 2
18+
True
19+
20+
>>> from django.contrib.localflavor.uy.forms import UYCIField
21+
>>> f = UYCIField()
22+
>>> f.clean('4098053')
23+
u'4098053'
24+
>>> f.clean('409805-3')
25+
u'409805-3'
26+
>>> f.clean('409.805-3')
27+
u'409.805-3'
28+
>>> f.clean('10054112')
29+
u'10054112'
30+
>>> f.clean('1005411-2')
31+
u'1005411-2'
32+
>>> f.clean('1.005.411-2')
33+
u'1.005.411-2'
34+
>>> f.clean('foo')
35+
Traceback (most recent call last):
36+
...
37+
ValidationError: [u'Enter a valid CI number in X.XXX.XXX-X,XXXXXXX-X or XXXXXXXX format.']
38+
>>> f.clean('409805-2')
39+
Traceback (most recent call last):
40+
...
41+
ValidationError: [u'Enter a valid CI number.']
42+
>>> f.clean('1.005.411-5')
43+
Traceback (most recent call last):
44+
...
45+
ValidationError: [u'Enter a valid CI number.']
46+
"""

tests/regressiontests/forms/tests.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
from localflavor.sk import tests as localflavor_sk_tests
2626
from localflavor.uk import tests as localflavor_uk_tests
2727
from localflavor.us import tests as localflavor_us_tests
28+
from localflavor.uy import tests as localflavor_uy_tests
2829
from localflavor.za import tests as localflavor_za_tests
2930
from regressions import tests as regression_tests
3031
from util import tests as util_tests
@@ -61,6 +62,7 @@
6162
'localflavor_sk_tests': localflavor_sk_tests,
6263
'localflavor_uk_tests': localflavor_uk_tests,
6364
'localflavor_us_tests': localflavor_us_tests,
65+
'localflavor_uy_tests': localflavor_uy_tests,
6466
'localflavor_za_tests': localflavor_za_tests,
6567
'regression_tests': regression_tests,
6668
'formset_tests': formset_tests,

0 commit comments

Comments
 (0)