Add Django-1.2.1
[frozenviper.git] / Django-1.2.1 / build / lib.linux-i686-2.6 / django / contrib / localflavor / se / forms.py
blob951f4f8d55364269ba7b69834626ba3b84c4ce21
1 # -*- coding: utf-8 -*-
2 """
3 Swedish specific Form helpers
4 """
5 import re
6 from django import forms
7 from django.utils.translation import ugettext_lazy as _
8 from django.core.validators import EMPTY_VALUES
9 from django.contrib.localflavor.se.utils import (id_number_checksum,
10 validate_id_birthday, format_personal_id_number, valid_organisation,
11 format_organisation_number)
13 __all__ = ('SECountySelect', 'SEOrganisationNumberField',
14 'SEPersonalIdentityNumberField', 'SEPostalCodeField')
16 SWEDISH_ID_NUMBER = re.compile(r'^(?P<century>\d{2})?(?P<year>\d{2})(?P<month>\d{2})(?P<day>\d{2})(?P<sign>[\-+])?(?P<serial>\d{3})(?P<checksum>\d)$')
17 SE_POSTAL_CODE = re.compile(r'^[1-9]\d{2} ?\d{2}$')
19 class SECountySelect(forms.Select):
20 """
21 A Select form widget that uses a list of the Swedish counties (län) as its
22 choices.
24 The cleaned value is the official county code -- see
25 http://en.wikipedia.org/wiki/Counties_of_Sweden for a list.
26 """
28 def __init__(self, attrs=None):
29 from se_counties import COUNTY_CHOICES
30 super(SECountySelect, self).__init__(attrs=attrs,
31 choices=COUNTY_CHOICES)
33 class SEOrganisationNumberField(forms.CharField):
34 """
35 A form field that validates input as a Swedish organisation number
36 (organisationsnummer).
38 It accepts the same input as SEPersonalIdentityField (for sole
39 proprietorships (enskild firma). However, co-ordination numbers are not
40 accepted.
42 It also accepts ordinary Swedish organisation numbers with the format
43 NNNNNNNNNN.
45 The return value will be YYYYMMDDXXXX for sole proprietors, and NNNNNNNNNN
46 for other organisations.
47 """
49 default_error_messages = {
50 'invalid': _('Enter a valid Swedish organisation number.'),
53 def clean(self, value):
54 value = super(SEOrganisationNumberField, self).clean(value)
56 if value in EMPTY_VALUES:
57 return u''
59 match = SWEDISH_ID_NUMBER.match(value)
60 if not match:
61 raise forms.ValidationError(self.error_messages['invalid'])
63 gd = match.groupdict()
65 # Compare the calculated value with the checksum
66 if id_number_checksum(gd) != int(gd['checksum']):
67 raise forms.ValidationError(self.error_messages['invalid'])
69 # First: check if this is a real organisation_number
70 if valid_organisation(gd):
71 return format_organisation_number(gd)
73 # Is this a single properitor (enskild firma)?
74 try:
75 birth_day = validate_id_birthday(gd, False)
76 return format_personal_id_number(birth_day, gd)
77 except ValueError:
78 raise forms.ValidationError(self.error_messages['invalid'])
81 class SEPersonalIdentityNumberField(forms.CharField):
82 """
83 A form field that validates input as a Swedish personal identity number
84 (personnummer).
86 The correct formats are YYYYMMDD-XXXX, YYYYMMDDXXXX, YYMMDD-XXXX,
87 YYMMDDXXXX and YYMMDD+XXXX.
89 A + indicates that the person is older than 100 years, which will be taken
90 into consideration when the date is validated.
92 The checksum will be calculated and checked. The birth date is checked to
93 be a valid date.
95 By default, co-ordination numbers (samordningsnummer) will be accepted. To
96 only allow real personal identity numbers, pass the keyword argument
97 coordination_number=False to the constructor.
99 The cleaned value will always have the format YYYYMMDDXXXX.
102 def __init__(self, coordination_number=True, *args, **kwargs):
103 self.coordination_number = coordination_number
104 super(SEPersonalIdentityNumberField, self).__init__(*args, **kwargs)
106 default_error_messages = {
107 'invalid': _('Enter a valid Swedish personal identity number.'),
108 'coordination_number': _('Co-ordination numbers are not allowed.'),
111 def clean(self, value):
112 value = super(SEPersonalIdentityNumberField, self).clean(value)
114 if value in EMPTY_VALUES:
115 return u''
117 match = SWEDISH_ID_NUMBER.match(value)
118 if match is None:
119 raise forms.ValidationError(self.error_messages['invalid'])
121 gd = match.groupdict()
123 # compare the calculated value with the checksum
124 if id_number_checksum(gd) != int(gd['checksum']):
125 raise forms.ValidationError(self.error_messages['invalid'])
127 # check for valid birthday
128 try:
129 birth_day = validate_id_birthday(gd)
130 except ValueError:
131 raise forms.ValidationError(self.error_messages['invalid'])
133 # make sure that co-ordination numbers do not pass if not allowed
134 if not self.coordination_number and int(gd['day']) > 60:
135 raise forms.ValidationError(self.error_messages['coordination_number'])
137 return format_personal_id_number(birth_day, gd)
140 class SEPostalCodeField(forms.RegexField):
142 A form field that validates input as a Swedish postal code (postnummer).
143 Valid codes consist of five digits (XXXXX). The number can optionally be
144 formatted with a space after the third digit (XXX XX).
146 The cleaned value will never contain the space.
149 default_error_messages = {
150 'invalid': _('Enter a Swedish postal code in the format XXXXX.'),
153 def __init__(self, *args, **kwargs):
154 super(SEPostalCodeField, self).__init__(SE_POSTAL_CODE, *args, **kwargs)
156 def clean(self, value):
157 return super(SEPostalCodeField, self).clean(value).replace(' ', '')