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