Removed django.contrib.localflavor.

Each localflavor lives on as a separate app.
This commit is contained in:
Aymeric Augustin 2012-12-24 23:10:40 +01:00
parent b2d20e9826
commit f27a4ee327
304 changed files with 49 additions and 257012 deletions

View File

@ -57,11 +57,6 @@ file_filter = django/contrib/humanize/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/humanize/locale/en/LC_MESSAGES/django.po source_file = django/contrib/humanize/locale/en/LC_MESSAGES/django.po
source_lang = en source_lang = en
[django.contrib-localflavor]
file_filter = django/contrib/localflavor/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/localflavor/locale/en/LC_MESSAGES/django.po
source_lang = en
[django.contrib-messages] [django.contrib-messages]
file_filter = django/contrib/messages/locale/<lang>/LC_MESSAGES/django.po file_filter = django/contrib/messages/locale/<lang>/LC_MESSAGES/django.po
source_file = django/contrib/messages/locale/en/LC_MESSAGES/django.po source_file = django/contrib/messages/locale/en/LC_MESSAGES/django.po

View File

@ -1,5 +1,4 @@
from django.contrib.gis.db import models from django.contrib.gis.db import models
from django.contrib.localflavor.us.models import USStateField
from django.utils.encoding import python_2_unicode_compatible from django.utils.encoding import python_2_unicode_compatible
@python_2_unicode_compatible @python_2_unicode_compatible
@ -11,7 +10,7 @@ class Location(models.Model):
@python_2_unicode_compatible @python_2_unicode_compatible
class City(models.Model): class City(models.Model):
name = models.CharField(max_length=50) name = models.CharField(max_length=50)
state = USStateField() state = models.CharField(max_length=2)
location = models.ForeignKey(Location) location = models.ForeignKey(Location)
objects = models.GeoManager() objects = models.GeoManager()
def __str__(self): return self.name def __str__(self): return self.name

View File

@ -16,7 +16,6 @@ from django.contrib.gis.gdal import (CoordTransform, DataSource,
from django.contrib.gis.gdal.field import ( from django.contrib.gis.gdal.field import (
OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString, OFTTime) OFTDate, OFTDateTime, OFTInteger, OFTReal, OFTString, OFTTime)
from django.db import models, transaction from django.db import models, transaction
from django.contrib.localflavor.us.models import USStateField
from django.utils import six from django.utils import six
from django.utils.encoding import force_text from django.utils.encoding import force_text
@ -55,7 +54,6 @@ class LayerMapping(object):
models.SlugField : OFTString, models.SlugField : OFTString,
models.TextField : OFTString, models.TextField : OFTString,
models.URLField : OFTString, models.URLField : OFTString,
USStateField : OFTString,
models.BigIntegerField : (OFTInteger, OFTReal, OFTString), models.BigIntegerField : (OFTInteger, OFTReal, OFTString),
models.SmallIntegerField : (OFTInteger, OFTReal, OFTString), models.SmallIntegerField : (OFTInteger, OFTReal, OFTString),
models.PositiveSmallIntegerField : (OFTInteger, OFTReal, OFTString), models.PositiveSmallIntegerField : (OFTInteger, OFTReal, OFTString),

View File

@ -1,2 +0,0 @@
import warnings
warnings.warn("django.contrib.localflavor is deprecated. Use the separate django-localflavor-* packages instead.", DeprecationWarning)

View File

@ -1,37 +0,0 @@
# -*- coding: utf-8 -*-
"""
A list of Argentinean provinces and autonomous cities as `choices` in a
formfield. From
http://www.argentina.gov.ar/argentina/portal/paginas.dhtml?pagina=425
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""
from __future__ import unicode_literals
PROVINCE_CHOICES = (
('B', 'Buenos Aires'),
('K', 'Catamarca'),
('H', 'Chaco'),
('U', 'Chubut'),
('C', 'Ciudad Autónoma de Buenos Aires'),
('X', 'Córdoba'),
('W', 'Corrientes'),
('E', 'Entre Ríos'),
('P', 'Formosa'),
('Y', 'Jujuy'),
('L', 'La Pampa'),
('F', 'La Rioja'),
('M', 'Mendoza'),
('N', 'Misiones'),
('Q', 'Neuquén'),
('R', 'Río Negro'),
('A', 'Salta'),
('J', 'San Juan'),
('D', 'San Luis'),
('Z', 'Santa Cruz'),
('S', 'Santa Fe'),
('G', 'Santiago del Estero'),
('V', 'Tierra del Fuego, Antártida e Islas del Atlántico Sur'),
('T', 'Tucumán'),
)

View File

@ -1,128 +0,0 @@
# -*- coding: utf-8 -*-
"""
AR-specific Form helpers.
"""
from __future__ import absolute_import, unicode_literals
from django.contrib.localflavor.ar.ar_provinces import PROVINCE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import RegexField, CharField, Select
from django.utils.translation import ugettext_lazy as _
class ARProvinceSelect(Select):
"""
A Select widget that uses a list of Argentinean provinces/autonomous cities
as its choices.
"""
def __init__(self, attrs=None):
super(ARProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
class ARPostalCodeField(RegexField):
"""
A field that accepts a 'classic' NNNN Postal Code or a CPA.
See:
http://www.correoargentino.com.ar/cpa/que_es
http://www.correoargentino.com.ar/cpa/como_escribirlo
"""
default_error_messages = {
'invalid': _("Enter a postal code in the format NNNN or ANNNNAAA."),
}
def __init__(self, max_length=8, min_length=4, *args, **kwargs):
super(ARPostalCodeField, self).__init__(r'^\d{4}$|^[A-HJ-NP-Za-hj-np-z]\d{4}\D{3}$',
max_length, min_length, *args, **kwargs)
def clean(self, value):
value = super(ARPostalCodeField, self).clean(value)
if value in EMPTY_VALUES:
return ''
if len(value) not in (4, 8):
raise ValidationError(self.error_messages['invalid'])
if len(value) == 8:
return '%s%s%s' % (value[0].upper(), value[1:5], value[5:].upper())
return value
class ARDNIField(CharField):
"""
A field that validates 'Documento Nacional de Identidad' (DNI) numbers.
"""
default_error_messages = {
'invalid': _("This field requires only numbers."),
'max_digits': _("This field requires 7 or 8 digits."),
}
def __init__(self, max_length=10, min_length=7, *args, **kwargs):
super(ARDNIField, self).__init__(max_length, min_length, *args,
**kwargs)
def clean(self, value):
"""
Value can be a string either in the [X]X.XXX.XXX or [X]XXXXXXX formats.
"""
value = super(ARDNIField, self).clean(value)
if value in EMPTY_VALUES:
return ''
if not value.isdigit():
value = value.replace('.', '')
if not value.isdigit():
raise ValidationError(self.error_messages['invalid'])
if len(value) not in (7, 8):
raise ValidationError(self.error_messages['max_digits'])
return value
class ARCUITField(RegexField):
"""
This field validates a CUIT (Código Único de Identificación Tributaria). A
CUIT is of the form XX-XXXXXXXX-V. The last digit is a check digit.
"""
default_error_messages = {
'invalid': _('Enter a valid CUIT in XX-XXXXXXXX-X or XXXXXXXXXXXX format.'),
'checksum': _("Invalid CUIT."),
'legal_type': _('Invalid legal type. Type must be 27, 20, 23 or 30.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(ARCUITField, self).__init__(r'^\d{2}-?\d{8}-?\d$',
max_length, min_length, *args, **kwargs)
def clean(self, value):
"""
Value can be either a string in the format XX-XXXXXXXX-X or an
11-digit number.
"""
value = super(ARCUITField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value, cd = self._canon(value)
if not value[:2] in ['27', '20', '23', '30']:
raise ValidationError(self.error_messages['legal_type'])
if self._calc_cd(value) != cd:
raise ValidationError(self.error_messages['checksum'])
return self._format(value, cd)
def _canon(self, cuit):
cuit = cuit.replace('-', '')
return cuit[:-1], cuit[-1]
def _calc_cd(self, cuit):
# Calculation code based on:
# http://es.wikipedia.org/wiki/C%C3%B3digo_%C3%9Anico_de_Identificaci%C3%B3n_Tributaria
mults = (5, 4, 3, 2, 7, 6, 5, 4, 3, 2)
tmp = sum([m * int(cuit[idx]) for idx, m in enumerate(mults)])
result = 11 - (tmp % 11)
if result == 11:
result = 0
elif result == 10:
result = 9
return str(result)
def _format(self, cuit, check_digit=None):
if check_digit is None:
check_digit = cuit[-1]
cuit = cuit[:-1]
return '%s-%s-%s' % (cuit[:2], cuit[2:], check_digit)

View File

@ -1,14 +0,0 @@
# -*- coding: utf-8 -*
from django.utils.translation import ugettext_lazy as _
STATE_CHOICES = (
('BL', _('Burgenland')),
('KA', _('Carinthia')),
('NO', _('Lower Austria')),
('OO', _('Upper Austria')),
('SA', _('Salzburg')),
('ST', _('Styria')),
('TI', _('Tyrol')),
('VO', _('Vorarlberg')),
('WI', _('Vienna')),
)

View File

@ -1,69 +0,0 @@
"""
AT-specific Form helpers
"""
from __future__ import unicode_literals
import re
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select
from django.utils.translation import ugettext_lazy as _
re_ssn = re.compile(r'^\d{4} \d{6}')
class ATZipCodeField(RegexField):
"""
A form field that validates its input is an Austrian postcode.
Accepts 4 digits (first digit must be greater than 0).
"""
default_error_messages = {
'invalid': _('Enter a zip code in the format XXXX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(ATZipCodeField, self).__init__(r'^[1-9]{1}\d{3}$',
max_length, min_length, *args, **kwargs)
class ATStateSelect(Select):
"""
A Select widget that uses a list of AT states as its choices.
"""
def __init__(self, attrs=None):
from django.contrib.localflavor.at.at_states import STATE_CHOICES
super(ATStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
class ATSocialSecurityNumberField(Field):
"""
Austrian Social Security numbers are composed of a 4 digits and 6 digits
field. The latter represents in most cases the person's birthdate while
the first 4 digits represent a 3-digits counter and a one-digit checksum.
The 6-digits field can also differ from the person's birthdate if the
3-digits counter suffered an overflow.
This code is based on information available on
http://de.wikipedia.org/wiki/Sozialversicherungsnummer#.C3.96sterreich
"""
default_error_messages = {
'invalid': _('Enter a valid Austrian Social Security Number in XXXX XXXXXX format.'),
}
def clean(self, value):
value = super(ATSocialSecurityNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ""
if not re_ssn.search(value):
raise ValidationError(self.error_messages['invalid'])
sqnr, date = value.split(" ")
sqnr, check = (sqnr[:3], (sqnr[3]))
if int(sqnr) < 100:
raise ValidationError(self.error_messages['invalid'])
res = int(sqnr[0])*3 + int(sqnr[1])*7 + int(sqnr[2])*9 \
+ int(date[0])*5 + int(date[1])*8 + int(date[2])*4 \
+ int(date[3])*2 + int(date[4])*1 + int(date[5])*6
res = res % 11
if res != int(check):
raise ValidationError(self.error_messages['invalid'])
return '%s%s %s'%(sqnr, check, date,)

View File

@ -1,17 +0,0 @@
"""
An alphabetical list of states for use as `choices` in a formfield.
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""
STATE_CHOICES = (
('ACT', 'Australian Capital Territory'),
('NSW', 'New South Wales'),
('NT', 'Northern Territory'),
('QLD', 'Queensland'),
('SA', 'South Australia'),
('TAS', 'Tasmania'),
('VIC', 'Victoria'),
('WA', 'Western Australia'),
)

View File

@ -1,60 +0,0 @@
"""
Australian-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.au.au_states import STATE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
PHONE_DIGITS_RE = re.compile(r'^(\d{10})$')
class AUPostCodeField(RegexField):
""" Australian post code field.
Assumed to be 4 digits.
Northern Territory 3-digit postcodes should have leading zero.
"""
default_error_messages = {
'invalid': _('Enter a 4 digit postcode.'),
}
def __init__(self, max_length=4, min_length=None, *args, **kwargs):
super(AUPostCodeField, self).__init__(r'^\d{4}$',
max_length, min_length, *args, **kwargs)
class AUPhoneNumberField(Field):
"""Australian phone number field."""
default_error_messages = {
'invalid': 'Phone numbers must contain 10 digits.',
}
def clean(self, value):
"""
Validate a phone number. Strips parentheses, whitespace and hyphens.
"""
super(AUPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\(|\)|\s+|-)', '', smart_text(value))
phone_match = PHONE_DIGITS_RE.search(value)
if phone_match:
return '%s' % phone_match.group(1)
raise ValidationError(self.error_messages['invalid'])
class AUStateSelect(Select):
"""
A Select widget that uses a list of Australian states/territories as its
choices.
"""
def __init__(self, attrs=None):
super(AUStateSelect, self).__init__(attrs, choices=STATE_CHOICES)

View File

@ -1,43 +0,0 @@
from django.utils.translation import ugettext_lazy as _
from django.db.models.fields import CharField
from django.contrib.localflavor.au.au_states import STATE_CHOICES
from django.contrib.localflavor.au import forms
class AUStateField(CharField):
description = _("Australian State")
def __init__(self, *args, **kwargs):
kwargs['choices'] = STATE_CHOICES
kwargs['max_length'] = 3
super(AUStateField, self).__init__(*args, **kwargs)
class AUPostCodeField(CharField):
description = _("Australian Postcode")
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 4
super(AUPostCodeField, self).__init__(*args, **kwargs)
def formfield(self, **kwargs):
defaults = {'form_class': forms.AUPostCodeField}
defaults.update(kwargs)
return super(AUPostCodeField, self).formfield(**defaults)
class AUPhoneNumberField(CharField):
description = _("Australian Phone number")
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 20
super(AUPhoneNumberField, self).__init__(*args, **kwargs)
def formfield(self, **kwargs):
defaults = {'form_class': forms.AUPhoneNumberField}
defaults.update(kwargs)
return super(AUPhoneNumberField, self).formfield(**defaults)

View File

@ -1,16 +0,0 @@
from django.utils.translation import ugettext_lazy as _
# ISO codes
PROVINCE_CHOICES = (
('VAN', _('Antwerp')),
('BRU', _('Brussels')),
('VOV', _('East Flanders')),
('VBR', _('Flemish Brabant')),
('WHT', _('Hainaut')),
('WLG', _('Liege')),
('VLI', _('Limburg')),
('WLX', _('Luxembourg')),
('WNA', _('Namur')),
('WBR', _('Walloon Brabant')),
('VWV', _('West Flanders'))
)

View File

@ -1,8 +0,0 @@
from django.utils.translation import ugettext_lazy as _
# ISO codes
REGION_CHOICES = (
('BRU', _('Brussels Capital Region')),
('VLG', _('Flemish Region')),
('WAL', _('Wallonia'))
)

View File

@ -1,71 +0,0 @@
"""
Belgium-specific Form helpers
"""
from __future__ import absolute_import
from django.contrib.localflavor.be.be_provinces import PROVINCE_CHOICES
from django.contrib.localflavor.be.be_regions import REGION_CHOICES
from django.forms.fields import RegexField, Select
from django.utils.translation import ugettext_lazy as _
class BEPostalCodeField(RegexField):
"""
A form field that validates its input as a belgium postal code.
Belgium postal code is a 4 digits string. The first digit indicates
the province (except for the 3ddd numbers that are shared by the
eastern part of Flemish Brabant and Limburg and the and 1ddd that
are shared by the Brussels Capital Region, the western part of
Flemish Brabant and Walloon Brabant)
"""
default_error_messages = {
'invalid': _(
'Enter a valid postal code in the range and format 1XXX - 9XXX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(BEPostalCodeField, self).__init__(r'^[1-9]\d{3}$',
max_length, min_length, *args, **kwargs)
class BEPhoneNumberField(RegexField):
"""
A form field that validates its input as a belgium phone number.
Landlines have a seven-digit subscriber number and a one-digit area code,
while smaller cities have a six-digit subscriber number and a two-digit
area code. Cell phones have a six-digit subscriber number and a two-digit
area code preceeded by the number 4.
0d ddd dd dd, 0d/ddd.dd.dd, 0d.ddd.dd.dd,
0dddddddd - dialling a bigger city
0dd dd dd dd, 0dd/dd.dd.dd, 0dd.dd.dd.dd,
0dddddddd - dialling a smaller city
04dd ddd dd dd, 04dd/ddd.dd.dd,
04dd.ddd.dd.dd, 04ddddddddd - dialling a mobile number
"""
default_error_messages = {
'invalid': _('Enter a valid phone number in one of the formats '
'0x xxx xx xx, 0xx xx xx xx, 04xx xx xx xx, '
'0x/xxx.xx.xx, 0xx/xx.xx.xx, 04xx/xx.xx.xx, '
'0x.xxx.xx.xx, 0xx.xx.xx.xx, 04xx.xx.xx.xx, '
'0xxxxxxxx or 04xxxxxxxx.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(BEPhoneNumberField, self).__init__(r'^[0]\d{1}[/. ]?\d{3}[. ]\d{2}[. ]?\d{2}$|^[0]\d{2}[/. ]?\d{2}[. ]?\d{2}[. ]?\d{2}$|^[0][4]\d{2}[/. ]?\d{2}[. ]?\d{2}[. ]?\d{2}$',
max_length, min_length, *args, **kwargs)
class BERegionSelect(Select):
"""
A Select widget that uses a list of belgium regions as its choices.
"""
def __init__(self, attrs=None):
super(BERegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
class BEProvinceSelect(Select):
"""
A Select widget that uses a list of belgium provinces as its choices.
"""
def __init__(self, attrs=None):
super(BEProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)

View File

@ -1,38 +0,0 @@
# -*- coding: utf-8 -*-
"""
An alphabetical list of Brazilian states for use as `choices` in a formfield.
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""
from __future__ import unicode_literals
STATE_CHOICES = (
('AC', 'Acre'),
('AL', 'Alagoas'),
('AP', 'Amapá'),
('AM', 'Amazonas'),
('BA', 'Bahia'),
('CE', 'Ceará'),
('DF', 'Distrito Federal'),
('ES', 'Espírito Santo'),
('GO', 'Goiás'),
('MA', 'Maranhão'),
('MT', 'Mato Grosso'),
('MS', 'Mato Grosso do Sul'),
('MG', 'Minas Gerais'),
('PA', 'Pará'),
('PB', 'Paraíba'),
('PR', 'Paraná'),
('PE', 'Pernambuco'),
('PI', 'Piauí'),
('RJ', 'Rio de Janeiro'),
('RN', 'Rio Grande do Norte'),
('RS', 'Rio Grande do Sul'),
('RO', 'Rondônia'),
('RR', 'Roraima'),
('SC', 'Santa Catarina'),
('SP', 'São Paulo'),
('SE', 'Sergipe'),
('TO', 'Tocantins'),
)

View File

@ -1,166 +0,0 @@
# -*- coding: utf-8 -*-
"""
BR-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.br.br_states import STATE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, CharField, Select
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
phone_digits_re = re.compile(r'^(\d{2})[-\.]?(\d{4})[-\.]?(\d{4})$')
class BRZipCodeField(RegexField):
default_error_messages = {
'invalid': _('Enter a zip code in the format XXXXX-XXX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(BRZipCodeField, self).__init__(r'^\d{5}-\d{3}$',
max_length, min_length, *args, **kwargs)
class BRPhoneNumberField(Field):
default_error_messages = {
'invalid': _('Phone numbers must be in XX-XXXX-XXXX format.'),
}
def clean(self, value):
super(BRPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\(|\)|\s+)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s-%s-%s' % (m.group(1), m.group(2), m.group(3))
raise ValidationError(self.error_messages['invalid'])
class BRStateSelect(Select):
"""
A Select widget that uses a list of Brazilian states/territories
as its choices.
"""
def __init__(self, attrs=None):
super(BRStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
class BRStateChoiceField(Field):
"""
A choice field that uses a list of Brazilian states as its choices.
"""
widget = Select
default_error_messages = {
'invalid': _('Select a valid brazilian state. That state is not one of the available states.'),
}
def __init__(self, required=True, widget=None, label=None,
initial=None, help_text=None):
super(BRStateChoiceField, self).__init__(required, widget, label,
initial, help_text)
self.widget.choices = STATE_CHOICES
def clean(self, value):
value = super(BRStateChoiceField, self).clean(value)
if value in EMPTY_VALUES:
value = ''
value = smart_text(value)
if value == '':
return value
valid_values = set([smart_text(k) for k, v in self.widget.choices])
if value not in valid_values:
raise ValidationError(self.error_messages['invalid'])
return value
def DV_maker(v):
if v >= 2:
return 11 - v
return 0
class BRCPFField(CharField):
"""
This field validate a CPF number or a CPF string. A CPF number is
compounded by XXX.XXX.XXX-VD. The two last digits are check digits.
More information:
http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas
"""
default_error_messages = {
'invalid': _("Invalid CPF number."),
'max_digits': _("This field requires at most 11 digits or 14 characters."),
'digits_only': _("This field requires only numbers."),
}
def __init__(self, max_length=14, min_length=11, *args, **kwargs):
super(BRCPFField, self).__init__(max_length, min_length, *args, **kwargs)
def clean(self, value):
"""
Value can be either a string in the format XXX.XXX.XXX-XX or an
11-digit number.
"""
value = super(BRCPFField, self).clean(value)
if value in EMPTY_VALUES:
return ''
orig_value = value[:]
if not value.isdigit():
value = re.sub("[-\.]", "", value)
try:
int(value)
except ValueError:
raise ValidationError(self.error_messages['digits_only'])
if len(value) != 11:
raise ValidationError(self.error_messages['max_digits'])
orig_dv = value[-2:]
new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(range(10, 1, -1))])
new_1dv = DV_maker(new_1dv % 11)
value = value[:-2] + str(new_1dv) + value[-1]
new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(range(11, 1, -1))])
new_2dv = DV_maker(new_2dv % 11)
value = value[:-1] + str(new_2dv)
if value[-2:] != orig_dv:
raise ValidationError(self.error_messages['invalid'])
return orig_value
class BRCNPJField(Field):
default_error_messages = {
'invalid': _("Invalid CNPJ number."),
'digits_only': _("This field requires only numbers."),
'max_digits': _("This field requires at least 14 digits"),
}
def clean(self, value):
"""
Value can be either a string in the format XX.XXX.XXX/XXXX-XX or a
group of 14 characters.
"""
value = super(BRCNPJField, self).clean(value)
if value in EMPTY_VALUES:
return ''
orig_value = value[:]
if not value.isdigit():
value = re.sub("[-/\.]", "", value)
try:
int(value)
except ValueError:
raise ValidationError(self.error_messages['digits_only'])
if len(value) != 14:
raise ValidationError(self.error_messages['max_digits'])
orig_dv = value[-2:]
new_1dv = sum([i * int(value[idx]) for idx, i in enumerate(list(range(5, 1, -1)) + list(range(9, 1, -1)))])
new_1dv = DV_maker(new_1dv % 11)
value = value[:-2] + str(new_1dv) + value[-1]
new_2dv = sum([i * int(value[idx]) for idx, i in enumerate(list(range(6, 1, -1)) + list(range(9, 1, -1)))])
new_2dv = DV_maker(new_2dv % 11)
value = value[:-1] + str(new_2dv)
if value[-2:] != orig_dv:
raise ValidationError(self.error_messages['invalid'])
return orig_value

View File

@ -1,63 +0,0 @@
"""
An alphabetical list of provinces and territories for use as `choices`
in a formfield., and a mapping of province misspellings/abbreviations to
normalized abbreviations
Source: http://www.canada.gc.ca/othergov/prov_e.html
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""
PROVINCE_CHOICES = (
('AB', 'Alberta'),
('BC', 'British Columbia'),
('MB', 'Manitoba'),
('NB', 'New Brunswick'),
('NL', 'Newfoundland and Labrador'),
('NT', 'Northwest Territories'),
('NS', 'Nova Scotia'),
('NU', 'Nunavut'),
('ON', 'Ontario'),
('PE', 'Prince Edward Island'),
('QC', 'Quebec'),
('SK', 'Saskatchewan'),
('YT', 'Yukon')
)
PROVINCES_NORMALIZED = {
'ab': 'AB',
'alberta': 'AB',
'bc': 'BC',
'b.c.': 'BC',
'british columbia': 'BC',
'mb': 'MB',
'manitoba': 'MB',
'nb': 'NB',
'new brunswick': 'NB',
'nf': 'NL',
'nl': 'NL',
'newfoundland': 'NL',
'newfoundland and labrador': 'NL',
'nt': 'NT',
'northwest territories': 'NT',
'ns': 'NS',
'nova scotia': 'NS',
'nu': 'NU',
'nunavut': 'NU',
'on': 'ON',
'ontario': 'ON',
'pe': 'PE',
'pei': 'PE',
'p.e.i.': 'PE',
'prince edward island': 'PE',
'pq' : 'QC',
'qc': 'QC',
'quebec': 'QC',
'sk': 'SK',
'saskatchewan': 'SK',
'yk': 'YT',
'yt': 'YT',
'yukon': 'YT',
'yukon territory': 'YT',
}

View File

@ -1,148 +0,0 @@
"""
Canada-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, CharField, Select
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
phone_digits_re = re.compile(r'^(?:1-?)?(\d{3})[-\.]?(\d{3})[-\.]?(\d{4})$')
sin_re = re.compile(r"^(\d{3})-(\d{3})-(\d{3})$")
class CAPostalCodeField(CharField):
"""
Canadian postal code field.
Validates against known invalid characters: D, F, I, O, Q, U
Additionally the first character cannot be Z or W.
For more info see:
http://www.canadapost.ca/tools/pg/manual/PGaddress-e.asp#1402170
"""
default_error_messages = {
'invalid': _('Enter a postal code in the format XXX XXX.'),
}
postcode_regex = re.compile(r'^([ABCEGHJKLMNPRSTVXY]\d[ABCEGHJKLMNPRSTVWXYZ]) *(\d[ABCEGHJKLMNPRSTVWXYZ]\d)$')
def clean(self, value):
value = super(CAPostalCodeField, self).clean(value)
if value in EMPTY_VALUES:
return ''
postcode = value.upper().strip()
m = self.postcode_regex.match(postcode)
if not m:
raise ValidationError(self.default_error_messages['invalid'])
return "%s %s" % (m.group(1), m.group(2))
class CAPhoneNumberField(Field):
"""Canadian phone number field."""
default_error_messages = {
'invalid': _('Phone numbers must be in XXX-XXX-XXXX format.'),
}
def clean(self, value):
"""Validate a phone number.
"""
super(CAPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\(|\)|\s+)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s-%s-%s' % (m.group(1), m.group(2), m.group(3))
raise ValidationError(self.error_messages['invalid'])
class CAProvinceField(Field):
"""
A form field that validates its input is a Canadian province name or abbreviation.
It normalizes the input to the standard two-leter postal service
abbreviation for the given province.
"""
default_error_messages = {
'invalid': _('Enter a Canadian province or territory.'),
}
def clean(self, value):
super(CAProvinceField, self).clean(value)
if value in EMPTY_VALUES:
return ''
try:
value = value.strip().lower()
except AttributeError:
pass
else:
# Load data in memory only when it is required, see also #17275
from .ca_provinces import PROVINCES_NORMALIZED
try:
return PROVINCES_NORMALIZED[value.strip().lower()]
except KeyError:
pass
raise ValidationError(self.error_messages['invalid'])
class CAProvinceSelect(Select):
"""
A Select widget that uses a list of Canadian provinces and
territories as its choices.
"""
def __init__(self, attrs=None):
# Load data in memory only when it is required, see also #17275
from .ca_provinces import PROVINCE_CHOICES
super(CAProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
class CASocialInsuranceNumberField(Field):
"""
A Canadian Social Insurance Number (SIN).
Checks the following rules to determine whether the number is valid:
* Conforms to the XXX-XXX-XXX format.
* Passes the check digit process "Luhn Algorithm"
See: http://en.wikipedia.org/wiki/Social_Insurance_Number
"""
default_error_messages = {
'invalid': _('Enter a valid Canadian Social Insurance number in XXX-XXX-XXX format.'),
}
def clean(self, value):
super(CASocialInsuranceNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
match = re.match(sin_re, value)
if not match:
raise ValidationError(self.error_messages['invalid'])
number = '%s-%s-%s' % (match.group(1), match.group(2), match.group(3))
check_number = '%s%s%s' % (match.group(1), match.group(2), match.group(3))
if not self.luhn_checksum_is_valid(check_number):
raise ValidationError(self.error_messages['invalid'])
return number
def luhn_checksum_is_valid(self, number):
"""
Checks to make sure that the SIN passes a luhn mod-10 checksum
See: http://en.wikipedia.org/wiki/Luhn_algorithm
"""
sum = 0
num_digits = len(number)
oddeven = num_digits & 1
for count in range(0, num_digits):
digit = int(number[count])
if not (( count & 1 ) ^ oddeven ):
digit = digit * 2
if digit > 9:
digit = digit - 9
sum = sum + digit
return ( (sum % 10) == 0 )

View File

@ -1,31 +0,0 @@
# -*- coding: utf-8 -*
from django.utils.translation import ugettext_lazy as _
STATE_CHOICES = (
('AG', _('Aargau')),
('AI', _('Appenzell Innerrhoden')),
('AR', _('Appenzell Ausserrhoden')),
('BS', _('Basel-Stadt')),
('BL', _('Basel-Land')),
('BE', _('Berne')),
('FR', _('Fribourg')),
('GE', _('Geneva')),
('GL', _('Glarus')),
('GR', _('Graubuenden')),
('JU', _('Jura')),
('LU', _('Lucerne')),
('NE', _('Neuchatel')),
('NW', _('Nidwalden')),
('OW', _('Obwalden')),
('SH', _('Schaffhausen')),
('SZ', _('Schwyz')),
('SO', _('Solothurn')),
('SG', _('St. Gallen')),
('TG', _('Thurgau')),
('TI', _('Ticino')),
('UR', _('Uri')),
('VS', _('Valais')),
('VD', _('Vaud')),
('ZG', _('Zug')),
('ZH', _('Zurich'))
)

View File

@ -1,122 +0,0 @@
"""
Swiss-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.ch.ch_states import STATE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
id_re = re.compile(r"^(?P<idnumber>\w{8})(?P<pos9>(\d{1}|<))(?P<checksum>\d{1})$")
phone_digits_re = re.compile(r'^0([1-9]{1})\d{8}$')
class CHZipCodeField(RegexField):
default_error_messages = {
'invalid': _('Enter a zip code in the format XXXX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(CHZipCodeField, self).__init__(r'^\d{4}$',
max_length, min_length, *args, **kwargs)
class CHPhoneNumberField(Field):
"""
Validate local Swiss phone number (not international ones)
The correct format is '0XX XXX XX XX'.
'0XX.XXX.XX.XX' and '0XXXXXXXXX' validate but are corrected to
'0XX XXX XX XX'.
"""
default_error_messages = {
'invalid': _('Phone numbers must be in 0XX XXX XX XX format.'),
}
def clean(self, value):
super(CHPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\.|\s|/|-)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s %s %s %s' % (value[0:3], value[3:6], value[6:8], value[8:10])
raise ValidationError(self.error_messages['invalid'])
class CHStateSelect(Select):
"""
A Select widget that uses a list of CH states as its choices.
"""
def __init__(self, attrs=None):
super(CHStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
class CHIdentityCardNumberField(Field):
"""
A Swiss identity card number.
Checks the following rules to determine whether the number is valid:
* Conforms to the X1234567<0 or 1234567890 format.
* Included checksums match calculated checksums
"""
default_error_messages = {
'invalid': _('Enter a valid Swiss identity or passport card number in X1234567<0 or 1234567890 format.'),
}
def has_valid_checksum(self, number):
given_number, given_checksum = number[:-1], number[-1]
new_number = given_number
calculated_checksum = 0
fragment = ""
parameter = 7
first = str(number[:1])
if first.isalpha():
num = ord(first.upper()) - 65
if num < 0 or num > 8:
return False
new_number = str(num) + new_number[1:]
new_number = new_number[:8] + '0'
if not new_number.isdigit():
return False
for i in range(len(new_number)):
fragment = int(new_number[i])*parameter
calculated_checksum += fragment
if parameter == 1:
parameter = 7
elif parameter == 3:
parameter = 1
elif parameter ==7:
parameter = 3
return str(calculated_checksum)[-1] == given_checksum
def clean(self, value):
super(CHIdentityCardNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
match = re.match(id_re, value)
if not match:
raise ValidationError(self.error_messages['invalid'])
idnumber, pos9, checksum = match.groupdict()['idnumber'], match.groupdict()['pos9'], match.groupdict()['checksum']
if idnumber == '00000000' or \
idnumber == 'A0000000':
raise ValidationError(self.error_messages['invalid'])
all_digits = "%s%s%s" % (idnumber, pos9, checksum)
if not self.has_valid_checksum(all_digits):
raise ValidationError(self.error_messages['invalid'])
return '%s%s%s' % (idnumber, pos9, checksum)

View File

@ -1,26 +0,0 @@
# -*- coding: utf-8 -*-
"""
A list of Chilean regions as `choices` in a formfield.
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""
from __future__ import unicode_literals
REGION_CHOICES = (
('RM', 'Región Metropolitana de Santiago'),
('I', 'Región de Tarapacá'),
('II', 'Región de Antofagasta'),
('III', 'Región de Atacama'),
('IV', 'Región de Coquimbo'),
('V', 'Región de Valparaíso'),
('VI', 'Región del Libertador Bernardo O\'Higgins'),
('VII', 'Región del Maule'),
('VIII','Región del Bío Bío'),
('IX', 'Región de la Araucanía'),
('X', 'Región de los Lagos'),
('XI', 'Región de Aysén del General Carlos Ibáñez del Campo'),
('XII', 'Región de Magallanes y la Antártica Chilena'),
('XIV', 'Región de Los Ríos'),
('XV', 'Región de Arica-Parinacota'),
)

View File

@ -1,97 +0,0 @@
"""
Chile specific form helpers.
"""
from __future__ import absolute_import, unicode_literals
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import RegexField, Select
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_text
from .cl_regions import REGION_CHOICES
class CLRegionSelect(Select):
"""
A Select widget that uses a list of Chilean Regions (Regiones)
as its choices.
"""
def __init__(self, attrs=None):
super(CLRegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
class CLRutField(RegexField):
"""
Chilean "Rol Unico Tributario" (RUT) field. This is the Chilean national
identification number.
Samples for testing are available from
https://palena.sii.cl/cvc/dte/ee_empresas_emisoras.html
"""
default_error_messages = {
'invalid': _('Enter a valid Chilean RUT.'),
'strict': _('Enter a valid Chilean RUT. The format is XX.XXX.XXX-X.'),
'checksum': _('The Chilean RUT is not valid.'),
}
def __init__(self, *args, **kwargs):
if 'strict' in kwargs:
del kwargs['strict']
super(CLRutField, self).__init__(r'^(\d{1,2}\.)?\d{3}\.\d{3}-[\dkK]$',
error_message=self.default_error_messages['strict'], *args, **kwargs)
else:
# In non-strict mode, accept RUTs that validate but do not exist in
# the real world.
super(CLRutField, self).__init__(r'^[\d\.]{1,11}-?[\dkK]$', *args, **kwargs)
def clean(self, value):
"""
Check and clean the Chilean RUT.
"""
super(CLRutField, self).clean(value)
if value in EMPTY_VALUES:
return ''
rut, verificador = self._canonify(value)
if self._algorithm(rut) == verificador:
return self._format(rut, verificador)
else:
raise ValidationError(self.error_messages['checksum'])
def _algorithm(self, rut):
"""
Takes RUT in pure canonical form, calculates the verifier digit.
"""
suma = 0
multi = 2
for r in rut[::-1]:
suma += int(r) * multi
multi += 1
if multi == 8:
multi = 2
return '0123456789K0'[11 - suma % 11]
def _canonify(self, rut):
"""
Turns the RUT into one normalized format. Returns a (rut, verifier)
tuple.
"""
rut = smart_text(rut).replace(' ', '').replace('.', '').replace('-', '')
return rut[:-1], rut[-1].upper()
def _format(self, code, verifier=None):
"""
Formats the RUT from canonical form to the common string representation.
If verifier=None, then the last digit in 'code' is the verifier.
"""
if verifier is None:
verifier = code[-1]
code = code[:-1]
while len(code) > 3 and '.' not in code[:3]:
pos = code.find('.')
if pos == -1:
new_dot = -3
else:
new_dot = pos - 3
code = code[:new_dot] + '.' + code[new_dot:]
return '%s-%s' % (code, verifier)

View File

@ -1,49 +0,0 @@
# -*- coding: utf-8 -*-
"""
An alphabetical list of provinces for use as `choices` in a formfield.
Reference:
http://en.wikipedia.org/wiki/ISO_3166-2:CN
http://en.wikipedia.org/wiki/Province_%28China%29
http://en.wikipedia.org/wiki/Direct-controlled_municipality
http://en.wikipedia.org/wiki/Autonomous_regions_of_China
"""
from __future__ import unicode_literals
CN_PROVINCE_CHOICES = (
("anhui", "安徽"),
("beijing", "北京"),
("chongqing", "重庆"),
("fujian", "福建"),
("gansu", "甘肃"),
("guangdong", "广东"),
("guangxi", "广西壮族自治区"),
("guizhou", "贵州"),
("hainan", "海南"),
("hebei", "河北"),
("heilongjiang", "黑龙江"),
("henan", "河南"),
("hongkong", "香港"),
("hubei", "湖北"),
("hunan", "湖南"),
("jiangsu", "江苏"),
("jiangxi", "江西"),
("jilin", "吉林"),
("liaoning", "辽宁"),
("macao", "澳门"),
("neimongol", "内蒙古自治区"),
("ningxia", "宁夏回族自治区"),
("qinghai", "青海"),
("shaanxi", "陕西"),
("shandong", "山东"),
("shanghai", "上海"),
("shanxi", "山西"),
("sichuan", "四川"),
("taiwan", "台湾"),
("tianjin", "天津"),
("xinjiang", "新疆维吾尔自治区"),
("xizang", "西藏自治区"),
("yunnan", "云南"),
("zhejiang", "浙江"),
)

View File

@ -1,214 +0,0 @@
# -*- coding: utf-8 -*-
"""
Chinese-specific form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.cn.cn_provinces import CN_PROVINCE_CHOICES
from django.forms import ValidationError
from django.forms.fields import CharField, RegexField, Select
from django.utils.translation import ugettext_lazy as _
__all__ = (
'CNProvinceSelect',
'CNPostCodeField',
'CNIDCardField',
'CNPhoneNumberField',
'CNCellNumberField',
)
ID_CARD_RE = r'^\d{15}(\d{2}[0-9xX])?$'
POST_CODE_RE = r'^\d{6}$'
PHONE_RE = r'^\d{3,4}-\d{7,8}(-\d+)?$'
CELL_RE = r'^1[358]\d{9}$'
# Valid location code used in id card checking algorithm
CN_LOCATION_CODES = (
11, # Beijing
12, # Tianjin
13, # Hebei
14, # Shanxi
15, # Nei Mongol
21, # Liaoning
22, # Jilin
23, # Heilongjiang
31, # Shanghai
32, # Jiangsu
33, # Zhejiang
34, # Anhui
35, # Fujian
36, # Jiangxi
37, # Shandong
41, # Henan
42, # Hubei
43, # Hunan
44, # Guangdong
45, # Guangxi
46, # Hainan
50, # Chongqing
51, # Sichuan
52, # Guizhou
53, # Yunnan
54, # Xizang
61, # Shaanxi
62, # Gansu
63, # Qinghai
64, # Ningxia
65, # Xinjiang
71, # Taiwan
81, # Hong Kong
91, # Macao
)
class CNProvinceSelect(Select):
"""
A select widget with list of Chinese provinces as choices.
"""
def __init__(self, attrs=None):
super(CNProvinceSelect, self).__init__(
attrs, choices=CN_PROVINCE_CHOICES,
)
class CNPostCodeField(RegexField):
"""
A form field that validates as Chinese post code.
Valid code is XXXXXX where X is digit.
"""
default_error_messages = {
'invalid': _('Enter a post code in the format XXXXXX.'),
}
def __init__(self, *args, **kwargs):
super(CNPostCodeField, self).__init__(POST_CODE_RE, *args, **kwargs)
class CNIDCardField(CharField):
"""
A form field that validates as Chinese Identification Card Number.
This field would check the following restrictions:
* the length could only be 15 or 18.
* if the length is 18, the last digit could be x or X.
* has a valid checksum.(length 18 only)
* has a valid birthdate.
* has a valid location.
The checksum algorithm is described in GB11643-1999.
"""
default_error_messages = {
'invalid': _('ID Card Number consists of 15 or 18 digits.'),
'checksum': _('Invalid ID Card Number: Wrong checksum'),
'birthday': _('Invalid ID Card Number: Wrong birthdate'),
'location': _('Invalid ID Card Number: Wrong location code'),
}
def __init__(self, max_length=18, min_length=15, *args, **kwargs):
super(CNIDCardField, self).__init__(max_length, min_length, *args,
**kwargs)
def clean(self, value):
"""
Check whether the input is a valid ID Card Number.
"""
# Check the length of the ID card number.
super(CNIDCardField, self).clean(value)
if not value:
return ""
# Check whether this ID card number has valid format
if not re.match(ID_CARD_RE, value):
raise ValidationError(self.error_messages['invalid'])
# Check the birthday of the ID card number.
if not self.has_valid_birthday(value):
raise ValidationError(self.error_messages['birthday'])
# Check the location of the ID card number.
if not self.has_valid_location(value):
raise ValidationError(self.error_messages['location'])
# Check the checksum of the ID card number.
value = value.upper()
if not self.has_valid_checksum(value):
raise ValidationError(self.error_messages['checksum'])
return '%s' % value
def has_valid_birthday(self, value):
"""
This function would grab the birthdate from the ID card number and test
whether it is a valid date.
"""
from datetime import datetime
if len(value) == 15:
# 1st generation ID card
time_string = value[6:12]
format_string = "%y%m%d"
else:
# 2nd generation ID card
time_string = value[6:14]
format_string = "%Y%m%d"
try:
datetime.strptime(time_string, format_string)
return True
except ValueError:
# invalid date
return False
def has_valid_location(self, value):
"""
This method checks if the first two digits in the ID Card are valid.
"""
return int(value[:2]) in CN_LOCATION_CODES
def has_valid_checksum(self, value):
"""
This method checks if the last letter/digit in value is valid
according to the algorithm the ID Card follows.
"""
# If the length of the number is not 18, then the number is a 1st
# generation ID card number, and there is no checksum to be checked.
if len(value) != 18:
return True
checksum_index = sum(
map(
lambda a,b:a*(ord(b)-ord('0')),
(7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2),
value[:17],
),
) % 11
return '10X98765432'[checksum_index] == value[-1]
class CNPhoneNumberField(RegexField):
"""
A form field that validates as Chinese phone number
A valid phone number could be like:
010-55555555
Considering there might be extension phone numbers, so this could also be:
010-55555555-35
"""
default_error_messages = {
'invalid': _('Enter a valid phone number.'),
}
def __init__(self, *args, **kwargs):
super(CNPhoneNumberField, self).__init__(PHONE_RE, *args, **kwargs)
class CNCellNumberField(RegexField):
"""
A form field that validates as Chinese cell number
A valid cell number could be like:
13012345678
We used a rough rule here, the first digit should be 1, the second could be
3, 5 and 8, the rest could be what so ever.
The length of the cell number should be 11.
"""
default_error_messages = {
'invalid': _('Enter a valid cell number.'),
}
def __init__(self, *args, **kwargs):
super(CNCellNumberField, self).__init__(CELL_RE, *args, **kwargs)

View File

@ -1,45 +0,0 @@
# -*- coding: utf-8 -*-
"""
A list of Colombian departaments as `choices` in a
formfield.
This exists in this standalone file so that it's only
imported into memory when explicitly needed.
"""
from __future__ import unicode_literals
DEPARTMENT_CHOICES = (
('AMA', 'Amazonas'),
('ANT', 'Antioquia'),
('ARA', 'Arauca'),
('ATL', 'Atlántico'),
('DC', 'Bogotá'),
('BOL', 'Bolívar'),
('BOY', 'Boyacá'),
('CAL', 'Caldas'),
('CAQ', 'Caquetá'),
('CAS', 'Casanare'),
('CAU', 'Cauca'),
('CES', 'Cesar'),
('CHO', 'Chocó'),
('COR', 'Córdoba'),
('CUN', 'Cundinamarca'),
('GUA', 'Guainía'),
('GUV', 'Guaviare'),
('HUI', 'Huila'),
('LAG', 'La Guajira'),
('MAG', 'Magdalena'),
('MET', 'Meta'),
('NAR', 'Nariño'),
('NSA', 'Norte de Santander'),
('PUT', 'Putumayo'),
('QUI', 'Quindío'),
('RIS', 'Risaralda'),
('SAP', 'San Andrés and Providencia'),
('SAN', 'Santander'),
('SUC', 'Sucre'),
('TOL', 'Tolima'),
('VAC', 'Valle del Cauca'),
('VAU', 'Vaupés'),
('VID', 'Vichada'),
)

View File

@ -1,16 +0,0 @@
"""
Colombian-specific form helpers.
"""
from __future__ import absolute_import
from django.contrib.localflavor.co.co_departments import DEPARTMENT_CHOICES
from django.forms.fields import Select
class CODepartmentSelect(Select):
"""
A Select widget that uses a list of Colombian states as its choices.
"""
def __init__(self, attrs=None):
super(CODepartmentSelect, self).__init__(attrs, choices=DEPARTMENT_CHOICES)

View File

@ -1,22 +0,0 @@
"""
Czech regions, translations get from http://www.crwflags.com/fotw/Flags/cz-re.html
"""
from django.utils.translation import ugettext_lazy as _
REGION_CHOICES = (
('PR', _('Prague')),
('CE', _('Central Bohemian Region')),
('SO', _('South Bohemian Region')),
('PI', _('Pilsen Region')),
('CA', _('Carlsbad Region')),
('US', _('Usti Region')),
('LB', _('Liberec Region')),
('HK', _('Hradec Region')),
('PA', _('Pardubice Region')),
('VY', _('Vysocina Region')),
('SM', _('South Moravian Region')),
('OL', _('Olomouc Region')),
('ZL', _('Zlin Region')),
('MS', _('Moravian-Silesian Region')),
)

View File

@ -1,136 +0,0 @@
"""
Czech-specific form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.cz.cz_regions import REGION_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Select, RegexField, Field
from django.utils.translation import ugettext_lazy as _
birth_number = re.compile(r'^(?P<birth>\d{6})/?(?P<id>\d{3,4})$')
ic_number = re.compile(r'^(?P<number>\d{7})(?P<check>\d)$')
class CZRegionSelect(Select):
"""
A select widget widget with list of Czech regions as choices.
"""
def __init__(self, attrs=None):
super(CZRegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
class CZPostalCodeField(RegexField):
"""
A form field that validates its input as Czech postal code.
Valid form is XXXXX or XXX XX, where X represents integer.
"""
default_error_messages = {
'invalid': _('Enter a postal code in the format XXXXX or XXX XX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(CZPostalCodeField, self).__init__(r'^\d{5}$|^\d{3} \d{2}$',
max_length, min_length, *args, **kwargs)
def clean(self, value):
"""
Validates the input and returns a string that contains only numbers.
Returns an empty string for empty values.
"""
v = super(CZPostalCodeField, self).clean(value)
return v.replace(' ', '')
class CZBirthNumberField(Field):
"""
Czech birth number field.
"""
default_error_messages = {
'invalid_format': _('Enter a birth number in the format XXXXXX/XXXX or XXXXXXXXXX.'),
'invalid': _('Enter a valid birth number.'),
}
def clean(self, value, gender=None):
super(CZBirthNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
match = re.match(birth_number, value)
if not match:
raise ValidationError(self.error_messages['invalid_format'])
birth, id = match.groupdict()['birth'], match.groupdict()['id']
# Three digits for verification number were used until 1. january 1954
if len(id) == 3:
return '%s' % value
# Birth number is in format YYMMDD. Females have month value raised by 50.
# In case that all possible number are already used (for given date),
# the month field is raised by 20.
month = int(birth[2:4])
if (not 1 <= month <= 12) and (not 21 <= month <= 32) and \
(not 51 <= month <= 62) and (not 71 <= month <= 82):
raise ValidationError(self.error_messages['invalid'])
day = int(birth[4:6])
if not (1 <= day <= 31):
raise ValidationError(self.error_messages['invalid'])
# Fourth digit has been added since 1. January 1954.
# It is modulo of dividing birth number and verification number by 11.
# If the modulo were 10, the last number was 0 (and therefore, the whole
# birth number wasn't divisable by 11. These number are no longer used (since 1985)
# and the condition 'modulo == 10' can be removed in 2085.
modulo = int(birth + id[:3]) % 11
if (modulo == int(id[-1])) or (modulo == 10 and id[-1] == '0'):
return '%s' % value
else:
raise ValidationError(self.error_messages['invalid'])
class CZICNumberField(Field):
"""
Czech IC number field.
"""
default_error_messages = {
'invalid': _('Enter a valid IC number.'),
}
def clean(self, value):
super(CZICNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
match = re.match(ic_number, value)
if not match:
raise ValidationError(self.error_messages['invalid'])
number, check = match.groupdict()['number'], int(match.groupdict()['check'])
sum = 0
weight = 8
for digit in number:
sum += int(digit)*weight
weight -= 1
remainder = sum % 11
# remainder is equal:
# 0 or 10: last digit is 1
# 1: last digit is 0
# in other case, last digit is 11 - remainder
if (not remainder % 10 and check == 1) or \
(remainder == 1 and check == 0) or \
(check == (11 - remainder)):
return '%s' % value
raise ValidationError(self.error_messages['invalid'])

View File

@ -1,21 +0,0 @@
# -*- coding: utf-8 -*
from django.utils.translation import ugettext_lazy as _
STATE_CHOICES = (
('BW', _('Baden-Wuerttemberg')),
('BY', _('Bavaria')),
('BE', _('Berlin')),
('BB', _('Brandenburg')),
('HB', _('Bremen')),
('HH', _('Hamburg')),
('HE', _('Hessen')),
('MV', _('Mecklenburg-Western Pomerania')),
('NI', _('Lower Saxony')),
('NW', _('North Rhine-Westphalia')),
('RP', _('Rhineland-Palatinate')),
('SL', _('Saarland')),
('SN', _('Saxony')),
('ST', _('Saxony-Anhalt')),
('SH', _('Schleswig-Holstein')),
('TH', _('Thuringia')),
)

View File

@ -1,88 +0,0 @@
"""
DE-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.de.de_states import STATE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select
from django.utils.translation import ugettext_lazy as _
id_re = re.compile(r"^(?P<residence>\d{10})(?P<origin>\w{1,3})[-\ ]?(?P<birthday>\d{7})[-\ ]?(?P<validity>\d{7})[-\ ]?(?P<checksum>\d{1})$")
class DEZipCodeField(RegexField):
default_error_messages = {
'invalid': _('Enter a zip code in the format XXXXX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(DEZipCodeField, self).__init__(r'^\d{5}$',
max_length, min_length, *args, **kwargs)
class DEStateSelect(Select):
"""
A Select widget that uses a list of DE states as its choices.
"""
def __init__(self, attrs=None):
super(DEStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
class DEIdentityCardNumberField(Field):
"""
A German identity card number.
Checks the following rules to determine whether the number is valid:
* Conforms to the XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.
* No group consists entirely of zeroes.
* Included checksums match calculated checksums
Algorithm is documented at http://de.wikipedia.org/wiki/Personalausweis
"""
default_error_messages = {
'invalid': _('Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.'),
}
def has_valid_checksum(self, number):
given_number, given_checksum = number[:-1], number[-1]
calculated_checksum = 0
fragment = ""
parameter = 7
for i in range(len(given_number)):
fragment = str(int(given_number[i]) * parameter)
if fragment.isalnum():
calculated_checksum += int(fragment[-1])
if parameter == 1:
parameter = 7
elif parameter == 3:
parameter = 1
elif parameter ==7:
parameter = 3
return str(calculated_checksum)[-1] == given_checksum
def clean(self, value):
super(DEIdentityCardNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
match = re.match(id_re, value)
if not match:
raise ValidationError(self.error_messages['invalid'])
gd = match.groupdict()
residence, origin = gd['residence'], gd['origin']
birthday, validity, checksum = gd['birthday'], gd['validity'], gd['checksum']
if residence == '0000000000' or birthday == '0000000' or validity == '0000000':
raise ValidationError(self.error_messages['invalid'])
all_digits = "%s%s%s%s" % (residence, birthday, validity, checksum)
if not self.has_valid_checksum(residence) or not self.has_valid_checksum(birthday) or \
not self.has_valid_checksum(validity) or not self.has_valid_checksum(all_digits):
raise ValidationError(self.error_messages['invalid'])
return '%s%s-%s-%s-%s' % (residence, origin, birthday, validity, checksum)

View File

@ -1,36 +0,0 @@
# -*- coding: utf-8 -*-
"""
A list of Ecuador departaments as `choices` in a
formfield.
This exists in this standalone file so that it's only
imported into memory when explicitly needed.
"""
from __future__ import unicode_literals
PROVINCE_CHOICES = (
('A', 'Azuay'),
('B', 'Bolívar'),
('F', 'Cañar'),
('C', 'Carchi'),
('H', 'Chimborazo'),
('X', 'Cotopaxi'),
('O', 'El Oro'),
('E', 'Esmeraldas'),
('W', 'Galápagos'),
('G', 'Guayas'),
('I', 'Imbabura'),
('L', 'Loja'),
('R', 'Los Ríos'),
('M', 'Manabí'),
('S', 'Morona Santiago'),
('N', 'Napo'),
('D', 'Orellana'),
('Y', 'Pastaza'),
('P', 'Pichincha'),
('SE', 'Santa Elena'),
('SD', 'Santo Domingo de los Tsáchilas'),
('U', 'Sucumbíos'),
('T', 'Tungurahua'),
('Z', 'Zamora Chinchipe'),
)

View File

@ -1,15 +0,0 @@
"""
Ecuador-specific form helpers.
"""
from __future__ import absolute_import
from django.contrib.localflavor.ec.ec_provinces import PROVINCE_CHOICES
from django.forms.fields import Select
class ECProvinceSelect(Select):
"""
A Select widget that uses a list of Ecuador provinces as its choices.
"""
def __init__(self, attrs=None):
super(ECProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)

View File

@ -1,58 +0,0 @@
# -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _
PROVINCE_CHOICES = (
('01', _('Araba')),
('02', _('Albacete')),
('03', _('Alacant')),
('04', _('Almeria')),
('05', _('Avila')),
('06', _('Badajoz')),
('07', _('Illes Balears')),
('08', _('Barcelona')),
('09', _('Burgos')),
('10', _('Caceres')),
('11', _('Cadiz')),
('12', _('Castello')),
('13', _('Ciudad Real')),
('14', _('Cordoba')),
('15', _('A Coruna')),
('16', _('Cuenca')),
('17', _('Girona')),
('18', _('Granada')),
('19', _('Guadalajara')),
('20', _('Guipuzkoa')),
('21', _('Huelva')),
('22', _('Huesca')),
('23', _('Jaen')),
('24', _('Leon')),
('25', _('Lleida')),
('26', _('La Rioja')),
('27', _('Lugo')),
('28', _('Madrid')),
('29', _('Malaga')),
('30', _('Murcia')),
('31', _('Navarre')),
('32', _('Ourense')),
('33', _('Asturias')),
('34', _('Palencia')),
('35', _('Las Palmas')),
('36', _('Pontevedra')),
('37', _('Salamanca')),
('38', _('Santa Cruz de Tenerife')),
('39', _('Cantabria')),
('40', _('Segovia')),
('41', _('Seville')),
('42', _('Soria')),
('43', _('Tarragona')),
('44', _('Teruel')),
('45', _('Toledo')),
('46', _('Valencia')),
('47', _('Valladolid')),
('48', _('Bizkaia')),
('49', _('Zamora')),
('50', _('Zaragoza')),
('51', _('Ceuta')),
('52', _('Melilla')),
)

View File

@ -1,23 +0,0 @@
# -*- coding: utf-8 -*-
from django.utils.translation import ugettext_lazy as _
REGION_CHOICES = (
('AN', _('Andalusia')),
('AR', _('Aragon')),
('O', _('Principality of Asturias')),
('IB', _('Balearic Islands')),
('PV', _('Basque Country')),
('CN', _('Canary Islands')),
('S', _('Cantabria')),
('CM', _('Castile-La Mancha')),
('CL', _('Castile and Leon')),
('CT', _('Catalonia')),
('EX', _('Extremadura')),
('GA', _('Galicia')),
('LO', _('La Rioja')),
('M', _('Madrid')),
('MU', _('Region of Murcia')),
('NA', _('Foral Community of Navarre')),
('VC', _('Valencian Community')),
)

View File

@ -1,189 +0,0 @@
# -*- coding: utf-8 -*-
"""
Spanish-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.es.es_provinces import PROVINCE_CHOICES
from django.contrib.localflavor.es.es_regions import REGION_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import RegexField, Select
from django.utils.translation import ugettext_lazy as _
class ESPostalCodeField(RegexField):
"""
A form field that validates its input as a spanish postal code.
Spanish postal code is a five digits string, with two first digits
between 01 and 52, assigned to provinces code.
"""
default_error_messages = {
'invalid': _('Enter a valid postal code in the range and format 01XXX - 52XXX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(ESPostalCodeField, self).__init__(
r'^(0[1-9]|[1-4][0-9]|5[0-2])\d{3}$',
max_length, min_length, *args, **kwargs)
class ESPhoneNumberField(RegexField):
"""
A form field that validates its input as a Spanish phone number.
Information numbers are ommited.
Spanish phone numbers are nine digit numbers, where first digit is 6 (for
cell phones), 8 (for special phones), or 9 (for landlines and special
phones)
TODO: accept and strip characters like dot, hyphen... in phone number
"""
default_error_messages = {
'invalid': _('Enter a valid phone number in one of the formats 6XXXXXXXX, 8XXXXXXXX or 9XXXXXXXX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(ESPhoneNumberField, self).__init__(r'^(6|7|8|9)\d{8}$',
max_length, min_length, *args, **kwargs)
class ESIdentityCardNumberField(RegexField):
"""
Spanish NIF/NIE/CIF (Fiscal Identification Number) code.
Validates three diferent formats:
NIF (individuals): 12345678A
CIF (companies): A12345678
NIE (foreigners): X12345678A
according to a couple of simple checksum algorithms.
Value can include a space or hyphen separator between number and letters.
Number length is not checked for NIF (or NIE), old values start with a 1,
and future values can contain digits greater than 8. The CIF control digit
can be a number or a letter depending on company type. Algorithm is not
public, and different authors have different opinions on which ones allows
letters, so both validations are assumed true for all types.
"""
default_error_messages = {
'invalid': _('Please enter a valid NIF, NIE, or CIF.'),
'invalid_only_nif': _('Please enter a valid NIF or NIE.'),
'invalid_nif': _('Invalid checksum for NIF.'),
'invalid_nie': _('Invalid checksum for NIE.'),
'invalid_cif': _('Invalid checksum for CIF.'),
}
def __init__(self, only_nif=False, max_length=None, min_length=None, *args, **kwargs):
self.only_nif = only_nif
self.nif_control = 'TRWAGMYFPDXBNJZSQVHLCKE'
self.cif_control = 'JABCDEFGHI'
self.cif_types = 'ABCDEFGHKLMNPQS'
self.nie_types = 'XT'
id_card_re = re.compile(r'^([%s]?)[ -]?(\d+)[ -]?([%s]?)$' % (self.cif_types + self.nie_types, self.nif_control + self.cif_control), re.IGNORECASE)
super(ESIdentityCardNumberField, self).__init__(id_card_re, max_length, min_length,
error_message=self.default_error_messages['invalid%s' % (self.only_nif and '_only_nif' or '')],
*args, **kwargs)
def clean(self, value):
super(ESIdentityCardNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
nif_get_checksum = lambda d: self.nif_control[int(d)%23]
value = value.upper().replace(' ', '').replace('-', '')
m = re.match(r'^([%s]?)[ -]?(\d+)[ -]?([%s]?)$' % (self.cif_types + self.nie_types, self.nif_control + self.cif_control), value)
letter1, number, letter2 = m.groups()
if not letter1 and letter2:
# NIF
if letter2 == nif_get_checksum(number):
return value
else:
raise ValidationError(self.error_messages['invalid_nif'])
elif letter1 in self.nie_types and letter2:
# NIE
if letter2 == nif_get_checksum(number):
return value
else:
raise ValidationError(self.error_messages['invalid_nie'])
elif not self.only_nif and letter1 in self.cif_types and len(number) in [7, 8]:
# CIF
if not letter2:
number, letter2 = number[:-1], int(number[-1])
checksum = cif_get_checksum(number)
if letter2 in (checksum, self.cif_control[checksum]):
return value
else:
raise ValidationError(self.error_messages['invalid_cif'])
else:
raise ValidationError(self.error_messages['invalid'])
class ESCCCField(RegexField):
"""
A form field that validates its input as a Spanish bank account or CCC
(Codigo Cuenta Cliente).
Spanish CCC is in format EEEE-OOOO-CC-AAAAAAAAAA where:
E = entity
O = office
C = checksum
A = account
It's also valid to use a space as delimiter, or to use no delimiter.
First checksum digit validates entity and office, and last one
validates account. Validation is done multiplying every digit of 10
digit value (with leading 0 if necessary) by number in its position in
string 1, 2, 4, 8, 5, 10, 9, 7, 3, 6. Sum resulting numbers and extract
it from 11. Result is checksum except when 10 then is 1, or when 11
then is 0.
TODO: allow IBAN validation too
"""
default_error_messages = {
'invalid': _('Please enter a valid bank account number in format XXXX-XXXX-XX-XXXXXXXXXX.'),
'checksum': _('Invalid checksum for bank account number.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(ESCCCField, self).__init__(r'^\d{4}[ -]?\d{4}[ -]?\d{2}[ -]?\d{10}$',
max_length, min_length, *args, **kwargs)
def clean(self, value):
super(ESCCCField, self).clean(value)
if value in EMPTY_VALUES:
return ''
control_str = [1, 2, 4, 8, 5, 10, 9, 7, 3, 6]
m = re.match(r'^(\d{4})[ -]?(\d{4})[ -]?(\d{2})[ -]?(\d{10})$', value)
entity, office, checksum, account = m.groups()
get_checksum = lambda d: str(11 - sum([int(digit) * int(control) for digit, control in zip(d, control_str)]) % 11).replace('10', '1').replace('11', '0')
if get_checksum('00' + entity + office) + get_checksum(account) == checksum:
return value
else:
raise ValidationError(self.error_messages['checksum'])
class ESRegionSelect(Select):
"""
A Select widget that uses a list of spanish regions as its choices.
"""
def __init__(self, attrs=None):
super(ESRegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
class ESProvinceSelect(Select):
"""
A Select widget that uses a list of spanish provinces as its choices.
"""
def __init__(self, attrs=None):
super(ESProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
def cif_get_checksum(number):
s1 = sum([int(digit) for pos, digit in enumerate(number) if int(pos) % 2])
s2 = sum([sum([int(unit) for unit in str(int(digit) * 2)]) for pos, digit in enumerate(number) if not int(pos) % 2])
return (10 - ((s1 + s2) % 10)) % 10

View File

@ -1,355 +0,0 @@
# -*- coding: utf-8 -*-
"""
An alphabetical list of Finnish municipalities for use as `choices` in a
formfield.
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""
from __future__ import unicode_literals
MUNICIPALITY_CHOICES = (
('akaa', "Akaa"),
('alajarvi', "Alajärvi"),
('alavieska', "Alavieska"),
('alavus', "Alavus"),
('artjarvi', "Artjärvi"),
('asikkala', "Asikkala"),
('askola', "Askola"),
('aura', "Aura"),
('brando', "Brändö"),
('eckero', "Eckerö"),
('enonkoski', "Enonkoski"),
('enontekio', "Enontekiö"),
('espoo', "Espoo"),
('eura', "Eura"),
('eurajoki', "Eurajoki"),
('evijarvi', "Evijärvi"),
('finstrom', "Finström"),
('forssa', "Forssa"),
('foglo', "Föglö"),
('geta', "Geta"),
('haapajarvi', "Haapajärvi"),
('haapavesi', "Haapavesi"),
('hailuoto', "Hailuoto"),
('halsua', "Halsua"),
('hamina', "Hamina"),
('hammarland', "Hammarland"),
('hankasalmi', "Hankasalmi"),
('hanko', "Hanko"),
('harjavalta', "Harjavalta"),
('hartola', "Hartola"),
('hattula', "Hattula"),
('haukipudas', "Haukipudas"),
('hausjarvi', "Hausjärvi"),
('heinola', "Heinola"),
('heinavesi', "Heinävesi"),
('helsinki', "Helsinki"),
('hirvensalmi', "Hirvensalmi"),
('hollola', "Hollola"),
('honkajoki', "Honkajoki"),
('huittinen', "Huittinen"),
('humppila', "Humppila"),
('hyrynsalmi', "Hyrynsalmi"),
('hyvinkaa', "Hyvinkää"),
('hameenkoski', "Hämeenkoski"),
('hameenkyro', "Hämeenkyrö"),
('hameenlinna', "Hämeenlinna"),
('ii', "Ii"),
('iisalmi', "Iisalmi"),
('iitti', "Iitti"),
('ikaalinen', "Ikaalinen"),
('ilmajoki', "Ilmajoki"),
('ilomantsi', "Ilomantsi"),
('imatra', "Imatra"),
('inari', "Inari"),
('inkoo', "Inkoo"),
('isojoki', "Isojoki"),
('isokyro', "Isokyrö"),
('jalasjarvi', "Jalasjärvi"),
('janakkala', "Janakkala"),
('joensuu', "Joensuu"),
('jokioinen', "Jokioinen"),
('jomala', "Jomala"),
('joroinen', "Joroinen"),
('joutsa', "Joutsa"),
('juankoski', "Juankoski"),
('juuka', "Juuka"),
('juupajoki', "Juupajoki"),
('juva', "Juva"),
('jyvaskyla', "Jyväskylä"),
('jamijarvi', "Jämijärvi"),
('jamsa', "Jämsä"),
('jarvenpaa', "Järvenpää"),
('kaarina', "Kaarina"),
('kaavi', "Kaavi"),
('kajaani', "Kajaani"),
('kalajoki', "Kalajoki"),
('kangasala', "Kangasala"),
('kangasniemi', "Kangasniemi"),
('kankaanpaa', "Kankaanpää"),
('kannonkoski', "Kannonkoski"),
('kannus', "Kannus"),
('karijoki', "Karijoki"),
('karjalohja', "Karjalohja"),
('karkkila', "Karkkila"),
('karstula', "Karstula"),
('karttula', "Karttula"),
('karvia', "Karvia"),
('kaskinen', "Kaskinen"),
('kauhajoki', "Kauhajoki"),
('kauhava', "Kauhava"),
('kauniainen', "Kauniainen"),
('kaustinen', "Kaustinen"),
('keitele', "Keitele"),
('kemi', "Kemi"),
('kemijarvi', "Kemijärvi"),
('keminmaa', "Keminmaa"),
('kemionsaari', "Kemiönsaari"),
('kempele', "Kempele"),
('kerava', "Kerava"),
('kerimaki', "Kerimäki"),
('kesalahti', "Kesälahti"),
('keuruu', "Keuruu"),
('kihnio', "Kihniö"),
('kiikoinen', "Kiikoinen"),
('kiiminki', "Kiiminki"),
('kinnula', "Kinnula"),
('kirkkonummi', "Kirkkonummi"),
('kitee', "Kitee"),
('kittila', "Kittilä"),
('kiuruvesi', "Kiuruvesi"),
('kivijarvi', "Kivijärvi"),
('kokemaki', "Kokemäki"),
('kokkola', "Kokkola"),
('kolari', "Kolari"),
('konnevesi', "Konnevesi"),
('kontiolahti', "Kontiolahti"),
('korsnas', "Korsnäs"),
('koskitl', "Koski Tl"),
('kotka', "Kotka"),
('kouvola', "Kouvola"),
('kristiinankaupunki', "Kristiinankaupunki"),
('kruunupyy', "Kruunupyy"),
('kuhmalahti', "Kuhmalahti"),
('kuhmo', "Kuhmo"),
('kuhmoinen', "Kuhmoinen"),
('kumlinge', "Kumlinge"),
('kuopio', "Kuopio"),
('kuortane', "Kuortane"),
('kurikka', "Kurikka"),
('kustavi', "Kustavi"),
('kuusamo', "Kuusamo"),
('kylmakoski', "Kylmäkoski"),
('kyyjarvi', "Kyyjärvi"),
('karkola', "Kärkölä"),
('karsamaki', "Kärsämäki"),
('kokar', "Kökar"),
('koylio', "Köyliö"),
('lahti', "Lahti"),
('laihia', "Laihia"),
('laitila', "Laitila"),
('lapinjarvi', "Lapinjärvi"),
('lapinlahti', "Lapinlahti"),
('lappajarvi', "Lappajärvi"),
('lappeenranta', "Lappeenranta"),
('lapua', "Lapua"),
('laukaa', "Laukaa"),
('lavia', "Lavia"),
('lemi', "Lemi"),
('lemland', "Lemland"),
('lempaala', "Lempäälä"),
('leppavirta', "Leppävirta"),
('lestijarvi', "Lestijärvi"),
('lieksa', "Lieksa"),
('lieto', "Lieto"),
('liminka', "Liminka"),
('liperi', "Liperi"),
('lohja', "Lohja"),
('loimaa', "Loimaa"),
('loppi', "Loppi"),
('loviisa', "Loviisa"),
('luhanka', "Luhanka"),
('lumijoki', "Lumijoki"),
('lumparland', "Lumparland"),
('luoto', "Luoto"),
('luumaki', "Luumäki"),
('luvia', "Luvia"),
('lansi-turunmaa', "Länsi-Turunmaa"),
('maalahti', "Maalahti"),
('maaninka', "Maaninka"),
('maarianhamina', "Maarianhamina"),
('marttila', "Marttila"),
('masku', "Masku"),
('merijarvi', "Merijärvi"),
('merikarvia', "Merikarvia"),
('miehikkala', "Miehikkälä"),
('mikkeli', "Mikkeli"),
('muhos', "Muhos"),
('multia', "Multia"),
('muonio', "Muonio"),
('mustasaari', "Mustasaari"),
('muurame', "Muurame"),
('mynamaki', "Mynämäki"),
('myrskyla', "Myrskylä"),
('mantsala', "Mäntsälä"),
('mantta-vilppula', "Mänttä-Vilppula"),
('mantyharju', "Mäntyharju"),
('naantali', "Naantali"),
('nakkila', "Nakkila"),
('nastola', "Nastola"),
('nilsia', "Nilsiä"),
('nivala', "Nivala"),
('nokia', "Nokia"),
('nousiainen', "Nousiainen"),
('nummi-pusula', "Nummi-Pusula"),
('nurmes', "Nurmes"),
('nurmijarvi', "Nurmijärvi"),
('narpio', "Närpiö"),
('oravainen', "Oravainen"),
('orimattila', "Orimattila"),
('oripaa', "Oripää"),
('orivesi', "Orivesi"),
('oulainen', "Oulainen"),
('oulu', "Oulu"),
('oulunsalo', "Oulunsalo"),
('outokumpu', "Outokumpu"),
('padasjoki', "Padasjoki"),
('paimio', "Paimio"),
('paltamo', "Paltamo"),
('parikkala', "Parikkala"),
('parkano', "Parkano"),
('pedersore', "Pedersöre"),
('pelkosenniemi', "Pelkosenniemi"),
('pello', "Pello"),
('perho', "Perho"),
('pertunmaa', "Pertunmaa"),
('petajavesi', "Petäjävesi"),
('pieksamaki', "Pieksämäki"),
('pielavesi', "Pielavesi"),
('pietarsaari', "Pietarsaari"),
('pihtipudas', "Pihtipudas"),
('pirkkala', "Pirkkala"),
('polvijarvi', "Polvijärvi"),
('pomarkku', "Pomarkku"),
('pori', "Pori"),
('pornainen', "Pornainen"),
('porvoo', "Porvoo"),
('posio', "Posio"),
('pudasjarvi', "Pudasjärvi"),
('pukkila', "Pukkila"),
('punkaharju', "Punkaharju"),
('punkalaidun', "Punkalaidun"),
('puolanka', "Puolanka"),
('puumala', "Puumala"),
('pyhtaa', "Pyhtää"),
('pyhajoki', "Pyhäjoki"),
('pyhajarvi', "Pyhäjärvi"),
('pyhanta', "Pyhäntä"),
('pyharanta', "Pyhäranta"),
('palkane', "Pälkäne"),
('poytya', "Pöytyä"),
('raahe', "Raahe"),
('raasepori', "Raasepori"),
('raisio', "Raisio"),
('rantasalmi', "Rantasalmi"),
('ranua', "Ranua"),
('rauma', "Rauma"),
('rautalampi', "Rautalampi"),
('rautavaara', "Rautavaara"),
('rautjarvi', "Rautjärvi"),
('reisjarvi', "Reisjärvi"),
('riihimaki', "Riihimäki"),
('ristiina', "Ristiina"),
('ristijarvi', "Ristijärvi"),
('rovaniemi', "Rovaniemi"),
('ruokolahti', "Ruokolahti"),
('ruovesi', "Ruovesi"),
('rusko', "Rusko"),
('raakkyla', "Rääkkylä"),
('saarijarvi', "Saarijärvi"),
('salla', "Salla"),
('salo', "Salo"),
('saltvik', "Saltvik"),
('sastamala', "Sastamala"),
('sauvo', "Sauvo"),
('savitaipale', "Savitaipale"),
('savonlinna', "Savonlinna"),
('savukoski', "Savukoski"),
('seinajoki', "Seinäjoki"),
('sievi', "Sievi"),
('siikainen', "Siikainen"),
('siikajoki', "Siikajoki"),
('siikalatva', "Siikalatva"),
('siilinjarvi', "Siilinjärvi"),
('simo', "Simo"),
('sipoo', "Sipoo"),
('siuntio', "Siuntio"),
('sodankyla', "Sodankylä"),
('soini', "Soini"),
('somero', "Somero"),
('sonkajarvi', "Sonkajärvi"),
('sotkamo', "Sotkamo"),
('sottunga', "Sottunga"),
('sulkava', "Sulkava"),
('sund', "Sund"),
('suomenniemi', "Suomenniemi"),
('suomussalmi', "Suomussalmi"),
('suonenjoki', "Suonenjoki"),
('sysma', "Sysmä"),
('sakyla', "Säkylä"),
('taipalsaari', "Taipalsaari"),
('taivalkoski', "Taivalkoski"),
('taivassalo', "Taivassalo"),
('tammela', "Tammela"),
('tampere', "Tampere"),
('tarvasjoki', "Tarvasjoki"),
('tervo', "Tervo"),
('tervola', "Tervola"),
('teuva', "Teuva"),
('tohmajarvi', "Tohmajärvi"),
('toholampi', "Toholampi"),
('toivakka', "Toivakka"),
('tornio', "Tornio"),
('turku', "Turku"),
('tuusniemi', "Tuusniemi"),
('tuusula', "Tuusula"),
('tyrnava', "Tyrnävä"),
('toysa', "Töysä"),
('ulvila', "Ulvila"),
('urjala', "Urjala"),
('utajarvi', "Utajärvi"),
('utsjoki', "Utsjoki"),
('uurainen', "Uurainen"),
('uusikaarlepyy', "Uusikaarlepyy"),
('uusikaupunki', "Uusikaupunki"),
('vaala', "Vaala"),
('vaasa', "Vaasa"),
('valkeakoski', "Valkeakoski"),
('valtimo', "Valtimo"),
('vantaa', "Vantaa"),
('varkaus', "Varkaus"),
('varpaisjarvi', "Varpaisjärvi"),
('vehmaa', "Vehmaa"),
('vesanto', "Vesanto"),
('vesilahti', "Vesilahti"),
('veteli', "Veteli"),
('vierema', "Vieremä"),
('vihanti', "Vihanti"),
('vihti', "Vihti"),
('viitasaari', "Viitasaari"),
('vimpeli', "Vimpeli"),
('virolahti', "Virolahti"),
('virrat', "Virrat"),
('vardo', "Vårdö"),
('vahakyro', "Vähäkyrö"),
('voyri-maksamaa', "Vöyri-Maksamaa"),
('yli-ii', "Yli-Ii"),
('ylitornio', "Ylitornio"),
('ylivieska', "Ylivieska"),
('ylojarvi', "Ylöjärvi"),
('ypaja', "Ypäjä"),
('ahtari', "Ähtäri"),
('aanekoski', "Äänekoski")
)

View File

@ -1,55 +0,0 @@
"""
FI-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.fi.fi_municipalities import MUNICIPALITY_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select
from django.utils.translation import ugettext_lazy as _
class FIZipCodeField(RegexField):
default_error_messages = {
'invalid': _('Enter a zip code in the format XXXXX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(FIZipCodeField, self).__init__(r'^\d{5}$',
max_length, min_length, *args, **kwargs)
class FIMunicipalitySelect(Select):
"""
A Select widget that uses a list of Finnish municipalities as its choices.
"""
def __init__(self, attrs=None):
super(FIMunicipalitySelect, self).__init__(attrs, choices=MUNICIPALITY_CHOICES)
class FISocialSecurityNumber(Field):
default_error_messages = {
'invalid': _('Enter a valid Finnish social security number.'),
}
def clean(self, value):
super(FISocialSecurityNumber, self).clean(value)
if value in EMPTY_VALUES:
return ''
checkmarks = "0123456789ABCDEFHJKLMNPRSTUVWXY"
result = re.match(r"""^
(?P<date>([0-2]\d|3[01])
(0\d|1[012])
(\d{2}))
[A+-]
(?P<serial>(\d{3}))
(?P<checksum>[%s])$""" % checkmarks, value, re.VERBOSE | re.IGNORECASE)
if not result:
raise ValidationError(self.error_messages['invalid'])
gd = result.groupdict()
checksum = int(gd['date'] + gd['serial'])
if checkmarks[checksum % len(checkmarks)] == gd['checksum'].upper():
return '%s' % value.upper()
raise ValidationError(self.error_messages['invalid'])

View File

@ -1,57 +0,0 @@
"""
FR-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.fr.fr_department import DEPARTMENT_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import CharField, RegexField, Select
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
phone_digits_re = re.compile(r'^0\d(\s|\.)?(\d{2}(\s|\.)?){3}\d{2}$')
class FRZipCodeField(RegexField):
default_error_messages = {
'invalid': _('Enter a zip code in the format XXXXX.'),
}
def __init__(self, max_length=5, min_length=5, *args, **kwargs):
super(FRZipCodeField, self).__init__(r'^\d{5}$',
max_length, min_length, *args, **kwargs)
class FRPhoneNumberField(CharField):
"""
Validate local French phone number (not international ones)
The correct format is '0X XX XX XX XX'.
'0X.XX.XX.XX.XX' and '0XXXXXXXXX' validate but are corrected to
'0X XX XX XX XX'.
"""
default_error_messages = {
'invalid': _('Phone numbers must be in 0X XX XX XX XX format.'),
}
def __init__(self, max_length=14, min_length=10, *args, **kwargs):
super(FRPhoneNumberField, self).__init__(
max_length, min_length, *args, **kwargs)
def clean(self, value):
super(FRPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\.|\s)', '', smart_text(value))
m = phone_digits_re.search(value)
if m:
return '%s %s %s %s %s' % (value[0:2], value[2:4], value[4:6], value[6:8], value[8:10])
raise ValidationError(self.error_messages['invalid'])
class FRDepartmentSelect(Select):
"""
A Select widget that uses a list of FR departments as its choices.
"""
def __init__(self, attrs=None):
super(FRDepartmentSelect, self).__init__(attrs, choices=DEPARTMENT_CHOICES)

View File

@ -1,118 +0,0 @@
# -*- coding: utf-8 -*-
# See the "Code officiel géographique" on the INSEE website <www.insee.fr>.
from __future__ import unicode_literals
DEPARTMENT_CHOICES = (
# Metropolitan departments
('01', '01 - Ain'),
('02', '02 - Aisne'),
('03', '03 - Allier'),
('04', '04 - Alpes-de-Haute-Provence'),
('05', '05 - Hautes-Alpes'),
('06', '06 - Alpes-Maritimes'),
('07', '07 - Ardèche'),
('08', '08 - Ardennes'),
('09', '09 - Ariège'),
('10', '10 - Aube'),
('11', '11 - Aude'),
('12', '12 - Aveyron'),
('13', '13 - Bouches-du-Rhône'),
('14', '14 - Calvados'),
('15', '15 - Cantal'),
('16', '16 - Charente'),
('17', '17 - Charente-Maritime'),
('18', '18 - Cher'),
('19', '19 - Corrèze'),
('2A', '2A - Corse-du-Sud'),
('2B', '2B - Haute-Corse'),
('21', '21 - Côte-d\'Or'),
('22', '22 - Côtes-d\'Armor'),
('23', '23 - Creuse'),
('24', '24 - Dordogne'),
('25', '25 - Doubs'),
('26', '26 - Drôme'),
('27', '27 - Eure'),
('28', '28 - Eure-et-Loir'),
('29', '29 - Finistère'),
('30', '30 - Gard'),
('31', '31 - Haute-Garonne'),
('32', '32 - Gers'),
('33', '33 - Gironde'),
('34', '34 - Hérault'),
('35', '35 - Ille-et-Vilaine'),
('36', '36 - Indre'),
('37', '37 - Indre-et-Loire'),
('38', '38 - Isère'),
('39', '39 - Jura'),
('40', '40 - Landes'),
('41', '41 - Loir-et-Cher'),
('42', '42 - Loire'),
('43', '43 - Haute-Loire'),
('44', '44 - Loire-Atlantique'),
('45', '45 - Loiret'),
('46', '46 - Lot'),
('47', '47 - Lot-et-Garonne'),
('48', '48 - Lozère'),
('49', '49 - Maine-et-Loire'),
('50', '50 - Manche'),
('51', '51 - Marne'),
('52', '52 - Haute-Marne'),
('53', '53 - Mayenne'),
('54', '54 - Meurthe-et-Moselle'),
('55', '55 - Meuse'),
('56', '56 - Morbihan'),
('57', '57 - Moselle'),
('58', '58 - Nièvre'),
('59', '59 - Nord'),
('60', '60 - Oise'),
('61', '61 - Orne'),
('62', '62 - Pas-de-Calais'),
('63', '63 - Puy-de-Dôme'),
('64', '64 - Pyrénées-Atlantiques'),
('65', '65 - Hautes-Pyrénées'),
('66', '66 - Pyrénées-Orientales'),
('67', '67 - Bas-Rhin'),
('68', '68 - Haut-Rhin'),
('69', '69 - Rhône'),
('70', '70 - Haute-Saône'),
('71', '71 - Saône-et-Loire'),
('72', '72 - Sarthe'),
('73', '73 - Savoie'),
('74', '74 - Haute-Savoie'),
('75', '75 - Paris'),
('76', '76 - Seine-Maritime'),
('77', '77 - Seine-et-Marne'),
('78', '78 - Yvelines'),
('79', '79 - Deux-Sèvres'),
('80', '80 - Somme'),
('81', '81 - Tarn'),
('82', '82 - Tarn-et-Garonne'),
('83', '83 - Var'),
('84', '84 - Vaucluse'),
('85', '85 - Vendée'),
('86', '86 - Vienne'),
('87', '87 - Haute-Vienne'),
('88', '88 - Vosges'),
('89', '89 - Yonne'),
('90', '90 - Territoire de Belfort'),
('91', '91 - Essonne'),
('92', '92 - Hauts-de-Seine'),
('93', '93 - Seine-Saint-Denis'),
('94', '94 - Val-de-Marne'),
('95', '95 - Val-d\'Oise'),
# Overseas departments, communities, and other territories
('971', '971 - Guadeloupe'),
('972', '972 - Martinique'),
('973', '973 - Guyane'),
('974', '974 - La Réunion'),
('975', '975 - Saint-Pierre-et-Miquelon'),
('976', '976 - Mayotte'),
('977', '977 - Saint-Barthélemy'),
('978', '978 - Saint-Martin'),
('984', '984 - Terres australes et antarctiques françaises'),
('986', '986 - Wallis et Futuna'),
('987', '987 - Polynésie française'),
('988', '988 - Nouvelle-Calédonie'),
('989', '989 - Île de Clipperton'),
)

View File

@ -1,55 +0,0 @@
"""
GB-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.gb.gb_regions import GB_NATIONS_CHOICES, GB_REGION_CHOICES
from django.forms.fields import CharField, Select
from django.forms import ValidationError
from django.utils.translation import ugettext_lazy as _
class GBPostcodeField(CharField):
"""
A form field that validates its input is a UK postcode.
The regular expression used is sourced from the schema for British Standard
BS7666 address types: http://www.govtalk.gov.uk/gdsc/schemas/bs7666-v2-0.xsd
The value is uppercased and a space added in the correct place, if required.
"""
default_error_messages = {
'invalid': _('Enter a valid postcode.'),
}
outcode_pattern = '[A-PR-UWYZ]([0-9]{1,2}|([A-HIK-Y][0-9](|[0-9]|[ABEHMNPRVWXY]))|[0-9][A-HJKSTUW])'
incode_pattern = '[0-9][ABD-HJLNP-UW-Z]{2}'
postcode_regex = re.compile(r'^(GIR 0AA|%s %s)$' % (outcode_pattern, incode_pattern))
space_regex = re.compile(r' *(%s)$' % incode_pattern)
def clean(self, value):
value = super(GBPostcodeField, self).clean(value)
if value == '':
return value
postcode = value.upper().strip()
# Put a single space before the incode (second part).
postcode = self.space_regex.sub(r' \1', postcode)
if not self.postcode_regex.search(postcode):
raise ValidationError(self.error_messages['invalid'])
return postcode
class GBCountySelect(Select):
"""
A Select widget that uses a list of UK Counties/Regions as its choices.
"""
def __init__(self, attrs=None):
super(GBCountySelect, self).__init__(attrs, choices=GB_REGION_CHOICES)
class GBNationSelect(Select):
"""
A Select widget that uses a list of UK Nations as its choices.
"""
def __init__(self, attrs=None):
super(GBNationSelect, self).__init__(attrs, choices=GB_NATIONS_CHOICES)

View File

@ -1,97 +0,0 @@
"""
Sources:
English regions: http://www.statistics.gov.uk/geography/downloads/31_10_01_REGION_names_and_codes_12_00.xls
Northern Ireland regions: http://en.wikipedia.org/wiki/List_of_Irish_counties_by_area
Welsh regions: http://en.wikipedia.org/wiki/Preserved_counties_of_Wales
Scottish regions: http://en.wikipedia.org/wiki/Regions_and_districts_of_Scotland
"""
from django.utils.translation import ugettext_lazy as _
ENGLAND_REGION_CHOICES = (
("Bedfordshire", _("Bedfordshire")),
("Buckinghamshire", _("Buckinghamshire")),
("Cambridgeshire", ("Cambridgeshire")),
("Cheshire", _("Cheshire")),
("Cornwall and Isles of Scilly", _("Cornwall and Isles of Scilly")),
("Cumbria", _("Cumbria")),
("Derbyshire", _("Derbyshire")),
("Devon", _("Devon")),
("Dorset", _("Dorset")),
("Durham", _("Durham")),
("East Sussex", _("East Sussex")),
("Essex", _("Essex")),
("Gloucestershire", _("Gloucestershire")),
("Greater London", _("Greater London")),
("Greater Manchester", _("Greater Manchester")),
("Hampshire", _("Hampshire")),
("Hertfordshire", _("Hertfordshire")),
("Kent", _("Kent")),
("Lancashire", _("Lancashire")),
("Leicestershire", _("Leicestershire")),
("Lincolnshire", _("Lincolnshire")),
("Merseyside", _("Merseyside")),
("Norfolk", _("Norfolk")),
("North Yorkshire", _("North Yorkshire")),
("Northamptonshire", _("Northamptonshire")),
("Northumberland", _("Northumberland")),
("Nottinghamshire", _("Nottinghamshire")),
("Oxfordshire", _("Oxfordshire")),
("Shropshire", _("Shropshire")),
("Somerset", _("Somerset")),
("South Yorkshire", _("South Yorkshire")),
("Staffordshire", _("Staffordshire")),
("Suffolk", _("Suffolk")),
("Surrey", _("Surrey")),
("Tyne and Wear", _("Tyne and Wear")),
("Warwickshire", _("Warwickshire")),
("West Midlands", _("West Midlands")),
("West Sussex", _("West Sussex")),
("West Yorkshire", _("West Yorkshire")),
("Wiltshire", _("Wiltshire")),
("Worcestershire", _("Worcestershire")),
)
NORTHERN_IRELAND_REGION_CHOICES = (
("County Antrim", _("County Antrim")),
("County Armagh", _("County Armagh")),
("County Down", _("County Down")),
("County Fermanagh", _("County Fermanagh")),
("County Londonderry", _("County Londonderry")),
("County Tyrone", _("County Tyrone")),
)
WALES_REGION_CHOICES = (
("Clwyd", _("Clwyd")),
("Dyfed", _("Dyfed")),
("Gwent", _("Gwent")),
("Gwynedd", _("Gwynedd")),
("Mid Glamorgan", _("Mid Glamorgan")),
("Powys", _("Powys")),
("South Glamorgan", _("South Glamorgan")),
("West Glamorgan", _("West Glamorgan")),
)
SCOTTISH_REGION_CHOICES = (
("Borders", _("Borders")),
("Central Scotland", _("Central Scotland")),
("Dumfries and Galloway", _("Dumfries and Galloway")),
("Fife", _("Fife")),
("Grampian", _("Grampian")),
("Highland", _("Highland")),
("Lothian", _("Lothian")),
("Orkney Islands", _("Orkney Islands")),
("Shetland Islands", _("Shetland Islands")),
("Strathclyde", _("Strathclyde")),
("Tayside", _("Tayside")),
("Western Isles", _("Western Isles")),
)
GB_NATIONS_CHOICES = (
("England", _("England")),
("Northern Ireland", _("Northern Ireland")),
("Scotland", _("Scotland")),
("Wales", _("Wales")),
)
GB_REGION_CHOICES = ENGLAND_REGION_CHOICES + NORTHERN_IRELAND_REGION_CHOICES + WALES_REGION_CHOICES + SCOTTISH_REGION_CHOICES

View File

@ -1,48 +0,0 @@
from django import forms
DEFAULT_DATE_INPUT_FORMATS = (
'%Y-%m-%d', '%d/%m/%Y', '%d/%m/%y', # '2006-10-25', '25/10/2006', '25/10/06'
'%b %d %Y', '%b %d, %Y', # 'Oct 25 2006', 'Oct 25, 2006'
'%d %b %Y', '%d %b, %Y', # '25 Oct 2006', '25 Oct, 2006'
'%B %d %Y', '%B %d, %Y', # 'October 25 2006', 'October 25, 2006'
'%d %B %Y', '%d %B, %Y', # '25 October 2006', '25 October, 2006'
)
DEFAULT_DATETIME_INPUT_FORMATS = (
'%Y-%m-%d %H:%M:%S', # '2006-10-25 14:30:59'
'%Y-%m-%d %H:%M', # '2006-10-25 14:30'
'%Y-%m-%d', # '2006-10-25'
'%d/%m/%Y %H:%M:%S', # '25/10/2006 14:30:59'
'%d/%m/%Y %H:%M', # '25/10/2006 14:30'
'%d/%m/%Y', # '25/10/2006'
'%d/%m/%y %H:%M:%S', # '25/10/06 14:30:59'
'%d/%m/%y %H:%M', # '25/10/06 14:30'
'%d/%m/%y', # '25/10/06'
)
class DateField(forms.DateField):
"""
A date input field which uses non-US date input formats by default.
"""
def __init__(self, input_formats=None, *args, **kwargs):
input_formats = input_formats or DEFAULT_DATE_INPUT_FORMATS
super(DateField, self).__init__(input_formats=input_formats, *args, **kwargs)
class DateTimeField(forms.DateTimeField):
"""
A date and time input field which uses non-US date and time input formats
by default.
"""
def __init__(self, input_formats=None, *args, **kwargs):
input_formats = input_formats or DEFAULT_DATETIME_INPUT_FORMATS
super(DateTimeField, self).__init__(input_formats=input_formats, *args, **kwargs)
class SplitDateTimeField(forms.SplitDateTimeField):
"""
Split date and time input fields which use non-US date and time input
formats by default.
"""
def __init__(self, input_date_formats=None, input_time_formats=None, *args, **kwargs):
input_date_formats = input_date_formats or DEFAULT_DATE_INPUT_FORMATS
super(SplitDateTimeField, self).__init__(input_date_formats=input_date_formats,
input_time_formats=input_time_formats, *args, **kwargs)

View File

@ -1,71 +0,0 @@
"""
Hong Kong specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.core.validators import EMPTY_VALUES
from django.forms import CharField
from django.forms import ValidationError
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
hk_phone_digits_re = re.compile(r'^(?:852-?)?(\d{4})[-\.]?(\d{4})$')
hk_special_numbers = ('999', '992', '112')
hk_phone_prefixes = ('2', '3', '5', '6', '8', '9')
hk_formats = ['XXXX-XXXX', '852-XXXX-XXXX', '(+852) XXXX-XXXX',
'XXXX XXXX', 'XXXXXXXX']
class HKPhoneNumberField(CharField):
"""
Validate Hong Kong phone number.
The input format can be either one of the followings:
'XXXX-XXXX', '852-XXXX-XXXX', '(+852) XXXX-XXXX',
'XXXX XXXX', or 'XXXXXXXX'.
The output format is 'XXXX-XXXX'.
Note: The phone number shall not start with 999, 992, or 112.
And, it should start with either 2, 3, 5, 6, 8, or 9.
Ref - http://en.wikipedia.org/wiki/Telephone_numbers_in_Hong_Kong
"""
default_error_messages = {
'disguise': _('Phone number should not start with ' \
'one of the followings: %s.' % \
', '.join(hk_special_numbers)),
'invalid': _('Phone number must be in one of the following formats: '
'%s.' % ', '.join(hk_formats)),
'prefix': _('Phone number should start with ' \
'one of the followings: %s.' % \
', '.join(hk_phone_prefixes)),
}
def __init__(self, *args, **kwargs):
super(HKPhoneNumberField, self).__init__(*args, **kwargs)
def clean(self, value):
super(HKPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('(\(|\)|\s+|\+)', '', smart_text(value))
m = hk_phone_digits_re.search(value)
if not m:
raise ValidationError(self.error_messages['invalid'])
value = '%s-%s' % (m.group(1), m.group(2))
for special in hk_special_numbers:
if value.startswith(special):
raise ValidationError(self.error_messages['disguise'])
prefix_found = map(lambda prefix: value.startswith(prefix),
hk_phone_prefixes)
if not any(prefix_found):
raise ValidationError(self.error_messages['prefix'])
return value

View File

@ -1,282 +0,0 @@
# -*- coding: utf-8 -*-
"""
HR-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import datetime
import re
from django.contrib.localflavor.hr.hr_choices import (
HR_LICENSE_PLATE_PREFIX_CHOICES, HR_COUNTY_CHOICES,
HR_PHONE_NUMBER_PREFIX_CHOICES)
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, Select, RegexField
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
jmbg_re = re.compile(r'^(?P<dd>\d{2})(?P<mm>\d{2})(?P<yyy>\d{3})' + \
r'(?P<rr>\d{2})(?P<bbb>\d{3})(?P<k>\d{1})$')
oib_re = re.compile(r'^\d{11}$')
plate_re = re.compile(r'^(?P<prefix>[A-ZČŠŽ]{2})' + \
r'(?P<number>\d{3,4})(?P<suffix>[ABCDEFGHIJKLMNOPRSTUVZ]{1,2})$')
postal_code_re = re.compile(r'^\d{5}$')
phone_re = re.compile(r'^(\+385|00385|0)(?P<prefix>\d{2})(?P<number>\d{6,7})$')
jmbag_re = re.compile(r'^601983(?P<copy>\d{1})1(?P<jmbag>\d{10})(?P<k>\d{1})$')
class HRCountySelect(Select):
"""
A Select widget that uses a list of counties of Croatia as its choices.
"""
def __init__(self, attrs=None):
super(HRCountySelect, self).__init__(attrs, choices=HR_COUNTY_CHOICES)
class HRLicensePlatePrefixSelect(Select):
"""
A Select widget that uses a list of vehicle license plate prefixes of
Croatia as its choices.
"""
def __init__(self, attrs=None):
super(HRLicensePlatePrefixSelect, self).__init__(attrs,
choices=HR_LICENSE_PLATE_PREFIX_CHOICES)
class HRPhoneNumberPrefixSelect(Select):
"""
A Select widget that uses a list of phone number prefixes of Croatia as its
choices.
"""
def __init__(self, attrs=None):
super(HRPhoneNumberPrefixSelect, self).__init__(attrs,
choices=HR_PHONE_NUMBER_PREFIX_CHOICES)
class HRJMBGField(Field):
"""
Unique Master Citizen Number (JMBG) field.
The number is still in use in Croatia, but it is being replaced by OIB.
Source: http://en.wikipedia.org/wiki/Unique_Master_Citizen_Number
For who might be reimplementing:
The "area" regular expression group is used to calculate the region where a
person was registered. Additional validation can be implemented in
accordance with it, however this could result in exclusion of legit
immigrated citizens. Therefore, this field works for any ex-Yugoslavia
country.
"""
default_error_messages = {
'invalid': _('Enter a valid 13 digit JMBG'),
'date': _('Error in date segment'),
}
def clean(self, value):
super(HRJMBGField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = value.strip()
matches = jmbg_re.search(value)
if matches is None:
raise ValidationError(self.error_messages['invalid'])
# Make sure the date part is correct.
dd = int(matches.group('dd'))
mm = int(matches.group('mm'))
yyy = int(matches.group('yyy'))
try:
datetime.date(yyy, mm, dd)
except ValueError:
raise ValidationError(self.error_messages['date'])
# Validate checksum.
k = matches.group('k')
checksum = 0
for i, j in zip(range(7, 1, -1), range(6)):
checksum += i * (int(value[j]) + int(value[13 - i]))
m = 11 - checksum % 11
if m == 10:
raise ValidationError(self.error_messages['invalid'])
if m == 11 and k != '0':
raise ValidationError(self.error_messages['invalid'])
if not str(m) == k:
raise ValidationError(self.error_messages['invalid'])
return '%s' % (value, )
class HROIBField(RegexField):
"""
Personal Identification Number of Croatia (OIB) field.
http://www.oib.hr/
"""
default_error_messages = {
'invalid': _('Enter a valid 11 digit OIB'),
}
def __init__(self, min_length=11, max_length=11, *args, **kwargs):
super(HROIBField, self).__init__(r'^\d{11}$',
min_length, max_length, *args, **kwargs)
def clean(self, value):
super(HROIBField, self).clean(value)
if value in EMPTY_VALUES:
return ''
return '%s' % (value, )
class HRLicensePlateField(Field):
"""
Vehicle license plate of Croatia field. Normalizes to the specific format
below. Suffix is constructed from the shared letters of the Croatian and
English alphabets.
Format examples:
SB 123-A
(but also supports more characters)
ZG 1234-AA
Used for standardized license plates only.
"""
default_error_messages = {
'invalid': _('Enter a valid vehicle license plate number'),
'area': _('Enter a valid location code'),
'number': _('Number part cannot be zero'),
}
def clean(self, value):
super(HRLicensePlateField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub(r'[\s\-]+', '', smart_text(value.strip())).upper()
matches = plate_re.search(value)
if matches is None:
raise ValidationError(self.error_messages['invalid'])
# Make sure the prefix is in the list of known codes.
prefix = matches.group('prefix')
if prefix not in [choice[0] for choice in HR_LICENSE_PLATE_PREFIX_CHOICES]:
raise ValidationError(self.error_messages['area'])
# Make sure the number portion is not zero.
number = matches.group('number')
if int(number) == 0:
raise ValidationError(self.error_messages['number'])
return '%s %s-%s' % (prefix,number,matches.group('suffix'), )
class HRPostalCodeField(Field):
"""
Postal code of Croatia field.
It consists of exactly five digits ranging from 10000 to possibly less than
60000.
http://www.posta.hr/main.aspx?id=66
"""
default_error_messages = {
'invalid': _('Enter a valid 5 digit postal code'),
}
def clean(self, value):
super(HRPostalCodeField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = value.strip()
if not postal_code_re.search(value):
raise ValidationError(self.error_messages['invalid'])
# Make sure the number is in valid range.
if not 9999<int(value)<60000:
raise ValidationError(self.error_messages['invalid'])
return '%s' % (value, )
class HRPhoneNumberField(Field):
"""
Phone number of Croatia field.
Format: Complete country code or leading zero, area code prefix, 6 or 7
digit number.
Validates fixed, mobile and FGSM numbers. Normalizes to a full number with
country code (+385 prefix).
"""
default_error_messages = {
'invalid': _('Enter a valid phone number'),
'area': _('Enter a valid area or mobile network code'),
'number': _('The phone nubmer is too long'),
}
def clean(self, value):
super(HRPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub(r'[\-\s\(\)]', '', smart_text(value))
matches = phone_re.search(value)
if matches is None:
raise ValidationError(self.error_messages['invalid'])
# Make sure the prefix is in the list of known codes.
prefix = matches.group('prefix')
number = matches.group('number')
if prefix[0] == '1':
number = prefix[1] + number
prefix = prefix[0]
if prefix not in [choice[0] for choice in HR_PHONE_NUMBER_PREFIX_CHOICES]:
raise ValidationError(self.error_messages['area'])
# Make sure the number is of adequate length.
if prefix=='1' and len(number)!=7:
raise ValidationError(self.error_messages['number'])
return '%s%s%s' % ('+385',prefix,number)
class HRJMBAGField(Field):
"""
Unique Master Academic Citizen Number of Croatia (JMBAG) field.
This number is used by college students and professors in Croatia.
http://www.cap.srce.hr/IzgledX.aspx
"""
default_error_messages = {
'invalid': _('Enter a valid 19 digit JMBAG starting with 601983'),
'copy': _('Card issue number cannot be zero'),
}
def clean(self, value):
super(HRJMBAGField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub(r'[\-\s]', '', value.strip())
matches = jmbag_re.search(value)
if matches is None:
raise ValidationError(self.error_messages['invalid'])
# Make sure the issue number is not zero.
if matches.group('copy')=='0':
raise ValidationError(self.error_messages['copy'])
# Validate checksum using Luhn algorithm.
num = [int(x) for x in value]
if not sum(num[::-2] + [sum(divmod(d * 2, 10)) for d in num[-2::-2]]) % 10 == 0:
raise ValidationError(self.error_messages['invalid'])
return '%s' % (value, )

View File

@ -1,112 +0,0 @@
# -*- coding: utf-8 -*-
"""
Sources:
Croatian Counties: http://en.wikipedia.org/wiki/ISO_3166-2:HR
Croatia doesn't have official abbreviations for counties.
The ones provided are in common use.
"""
from __future__ import unicode_literals
from django.utils.translation import ugettext_lazy as _
HR_COUNTY_CHOICES = (
('GZG', _('Grad Zagreb')),
('BBŽ', _('Bjelovarsko-bilogorska županija')),
('BPŽ', _('Brodsko-posavska županija')),
('DNŽ', _('Dubrovačko-neretvanska županija')),
('', _('Istarska županija')),
('', _('Karlovačka županija')),
('KKŽ', _('Koprivničko-križevačka županija')),
('KZŽ', _('Krapinsko-zagorska županija')),
('LSŽ', _('Ličko-senjska županija')),
('', _('Međimurska županija')),
('OBŽ', _('Osječko-baranjska županija')),
('PSŽ', _('Požeško-slavonska županija')),
('PGŽ', _('Primorsko-goranska županija')),
('SMŽ', _('Sisačko-moslavačka županija')),
('SDŽ', _('Splitsko-dalmatinska županija')),
('ŠKŽ', _('Šibensko-kninska županija')),
('', _('Varaždinska županija')),
('VPŽ', _('Virovitičko-podravska županija')),
('VSŽ', _('Vukovarsko-srijemska županija')),
('ZDŽ', _('Zadarska županija')),
('ZGŽ', _('Zagrebačka županija')),
)
"""
Sources:
http://hr.wikipedia.org/wiki/Dodatak:Popis_registracijskih_oznaka_za_cestovna_vozila_u_Hrvatskoj
Only common license plate prefixes are provided. Special cases and obsolete prefixes are omitted.
"""
HR_LICENSE_PLATE_PREFIX_CHOICES = (
('BJ', 'BJ'),
('BM', 'BM'),
('ČK', 'ČK'),
('DA', 'DA'),
('DE', 'DE'),
('DJ', 'DJ'),
('DU', 'DU'),
('GS', 'GS'),
('IM', 'IM'),
('KA', 'KA'),
('KC', 'KC'),
('KR', 'KR'),
('KT', 'KT'),
('', ''),
('MA', 'MA'),
('NA', 'NA'),
('NG', 'NG'),
('OG', 'OG'),
('OS', 'OS'),
('PU', 'PU'),
('', ''),
('RI', 'RI'),
('SB', 'SB'),
('SK', 'SK'),
('SL', 'SL'),
('ST', 'ST'),
('ŠI', 'ŠI'),
('VK', 'VK'),
('VT', 'VT'),
('VU', 'VU'),
('', ''),
('ZD', 'ZD'),
('ZG', 'ZG'),
('ŽU', 'ŽU'),
)
"""
The list includes county and cellular network phone number prefixes.
"""
HR_PHONE_NUMBER_PREFIX_CHOICES = (
('1', '01'),
('20', '020'),
('21', '021'),
('22', '022'),
('23', '023'),
('31', '031'),
('32', '032'),
('33', '033'),
('34', '034'),
('35', '035'),
('40', '040'),
('42', '042'),
('43', '043'),
('44', '044'),
('47', '047'),
('48', '048'),
('49', '049'),
('51', '051'),
('52', '052'),
('53', '053'),
('91', '091'),
('92', '092'),
('95', '095'),
('97', '097'),
('98', '098'),
('99', '099'),
)

View File

@ -1,217 +0,0 @@
"""
ID-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
import time
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, Select
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_text
postcode_re = re.compile(r'^[1-9]\d{4}$')
phone_re = re.compile(r'^(\+62|0)[2-9]\d{7,10}$')
plate_re = re.compile(r'^(?P<prefix>[A-Z]{1,2}) ' + \
r'(?P<number>\d{1,5})( (?P<suffix>([A-Z]{1,3}|[1-9][0-9]{,2})))?$')
nik_re = re.compile(r'^\d{16}$')
class IDPostCodeField(Field):
"""
An Indonesian post code field.
http://id.wikipedia.org/wiki/Kode_pos
"""
default_error_messages = {
'invalid': _('Enter a valid post code'),
}
def clean(self, value):
super(IDPostCodeField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = value.strip()
if not postcode_re.search(value):
raise ValidationError(self.error_messages['invalid'])
if int(value) < 10110:
raise ValidationError(self.error_messages['invalid'])
# 1xxx0
if value[0] == '1' and value[4] != '0':
raise ValidationError(self.error_messages['invalid'])
return '%s' % (value, )
class IDProvinceSelect(Select):
"""
A Select widget that uses a list of provinces of Indonesia as its
choices.
"""
def __init__(self, attrs=None):
# Load data in memory only when it is required, see also #17275
from django.contrib.localflavor.id.id_choices import PROVINCE_CHOICES
super(IDProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
class IDPhoneNumberField(Field):
"""
An Indonesian telephone number field.
http://id.wikipedia.org/wiki/Daftar_kode_telepon_di_Indonesia
"""
default_error_messages = {
'invalid': _('Enter a valid phone number'),
}
def clean(self, value):
super(IDPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
phone_number = re.sub(r'[\-\s\(\)]', '', smart_text(value))
if phone_re.search(phone_number):
return smart_text(value)
raise ValidationError(self.error_messages['invalid'])
class IDLicensePlatePrefixSelect(Select):
"""
A Select widget that uses a list of vehicle license plate prefix code
of Indonesia as its choices.
http://id.wikipedia.org/wiki/Tanda_Nomor_Kendaraan_Bermotor
"""
def __init__(self, attrs=None):
# Load data in memory only when it is required, see also #17275
from django.contrib.localflavor.id.id_choices import LICENSE_PLATE_PREFIX_CHOICES
super(IDLicensePlatePrefixSelect, self).__init__(attrs,
choices=LICENSE_PLATE_PREFIX_CHOICES)
class IDLicensePlateField(Field):
"""
An Indonesian vehicle license plate field.
http://id.wikipedia.org/wiki/Tanda_Nomor_Kendaraan_Bermotor
Plus: "B 12345 12"
"""
default_error_messages = {
'invalid': _('Enter a valid vehicle license plate number'),
}
def clean(self, value):
# Load data in memory only when it is required, see also #17275
from django.contrib.localflavor.id.id_choices import LICENSE_PLATE_PREFIX_CHOICES
super(IDLicensePlateField, self).clean(value)
if value in EMPTY_VALUES:
return ''
plate_number = re.sub(r'\s+', ' ',
smart_text(value.strip())).upper()
matches = plate_re.search(plate_number)
if matches is None:
raise ValidationError(self.error_messages['invalid'])
# Make sure prefix is in the list of known codes.
prefix = matches.group('prefix')
if prefix not in [choice[0] for choice in LICENSE_PLATE_PREFIX_CHOICES]:
raise ValidationError(self.error_messages['invalid'])
# Only Jakarta (prefix B) can have 3 letter suffix.
suffix = matches.group('suffix')
if suffix is not None and len(suffix) == 3 and prefix != 'B':
raise ValidationError(self.error_messages['invalid'])
# RI plates don't have suffix.
if prefix == 'RI' and suffix is not None and suffix != '':
raise ValidationError(self.error_messages['invalid'])
# Number can't be zero.
number = matches.group('number')
if number == '0':
raise ValidationError(self.error_messages['invalid'])
# CD, CC and B 12345 12
if len(number) == 5 or prefix in ('CD', 'CC'):
# suffix must be numeric and non-empty
if re.match(r'^\d+$', suffix) is None:
raise ValidationError(self.error_messages['invalid'])
# Known codes range is 12-124
if prefix in ('CD', 'CC') and not (12 <= int(number) <= 124):
raise ValidationError(self.error_messages['invalid'])
if len(number) == 5 and not (12 <= int(suffix) <= 124):
raise ValidationError(self.error_messages['invalid'])
else:
# suffix must be non-numeric
if suffix is not None and re.match(r'^[A-Z]{,3}$', suffix) is None:
raise ValidationError(self.error_messages['invalid'])
return plate_number
class IDNationalIdentityNumberField(Field):
"""
An Indonesian national identity number (NIK/KTP#) field.
http://id.wikipedia.org/wiki/Nomor_Induk_Kependudukan
xx.xxxx.ddmmyy.xxxx - 16 digits (excl. dots)
"""
default_error_messages = {
'invalid': _('Enter a valid NIK/KTP number'),
}
def clean(self, value):
super(IDNationalIdentityNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub(r'[\s.]', '', smart_text(value))
if not nik_re.search(value):
raise ValidationError(self.error_messages['invalid'])
if int(value) == 0:
raise ValidationError(self.error_messages['invalid'])
def valid_nik_date(year, month, day):
try:
t1 = (int(year), int(month), int(day), 0, 0, 0, 0, 0, -1)
d = time.mktime(t1)
t2 = time.localtime(d)
if t1[:3] != t2[:3]:
return False
else:
return True
except (OverflowError, ValueError):
return False
year = int(value[10:12])
month = int(value[8:10])
day = int(value[6:8])
current_year = time.localtime().tm_year
if year < int(str(current_year)[-2:]):
if not valid_nik_date(2000 + int(year), month, day):
raise ValidationError(self.error_messages['invalid'])
elif not valid_nik_date(1900 + int(year), month, day):
raise ValidationError(self.error_messages['invalid'])
if value[:6] == '000000' or value[12:] == '0000':
raise ValidationError(self.error_messages['invalid'])
return '%s.%s.%s.%s' % (value[:2], value[2:6], value[6:12], value[12:])

View File

@ -1,107 +0,0 @@
import warnings
from django.utils.translation import ugettext_lazy as _
# Reference: http://id.wikipedia.org/wiki/Daftar_provinsi_Indonesia
# Indonesia does not have an official Province code standard.
# I decided to use unambiguous and consistent (some are common) 3-letter codes.
warnings.warn(
'There have been recent changes to the ID localflavor. See the release notes for details',
RuntimeWarning
)
PROVINCE_CHOICES = (
('ACE', _('Aceh')),
('BLI', _('Bali')),
('BTN', _('Banten')),
('BKL', _('Bengkulu')),
('DIY', _('Yogyakarta')),
('JKT', _('Jakarta')),
('GOR', _('Gorontalo')),
('JMB', _('Jambi')),
('JBR', _('Jawa Barat')),
('JTG', _('Jawa Tengah')),
('JTM', _('Jawa Timur')),
('KBR', _('Kalimantan Barat')),
('KSL', _('Kalimantan Selatan')),
('KTG', _('Kalimantan Tengah')),
('KTM', _('Kalimantan Timur')),
('BBL', _('Kepulauan Bangka-Belitung')),
('KRI', _('Kepulauan Riau')),
('LPG', _('Lampung')),
('MLK', _('Maluku')),
('MUT', _('Maluku Utara')),
('NTB', _('Nusa Tenggara Barat')),
('NTT', _('Nusa Tenggara Timur')),
('PPA', _('Papua')),
('PPB', _('Papua Barat')),
('RIU', _('Riau')),
('SLB', _('Sulawesi Barat')),
('SLS', _('Sulawesi Selatan')),
('SLT', _('Sulawesi Tengah')),
('SLR', _('Sulawesi Tenggara')),
('SLU', _('Sulawesi Utara')),
('SMB', _('Sumatera Barat')),
('SMS', _('Sumatera Selatan')),
('SMU', _('Sumatera Utara')),
)
LICENSE_PLATE_PREFIX_CHOICES = (
('A', _('Banten')),
('AA', _('Magelang')),
('AB', _('Yogyakarta')),
('AD', _('Surakarta - Solo')),
('AE', _('Madiun')),
('AG', _('Kediri')),
('B', _('Jakarta')),
('BA', _('Sumatera Barat')),
('BB', _('Tapanuli')),
('BD', _('Bengkulu')),
('BE', _('Lampung')),
('BG', _('Sumatera Selatan')),
('BH', _('Jambi')),
('BK', _('Sumatera Utara')),
('BL', _('Nanggroe Aceh Darussalam')),
('BM', _('Riau')),
('BN', _('Kepulauan Bangka Belitung')),
('BP', _('Kepulauan Riau')),
('CC', _('Corps Consulate')),
('CD', _('Corps Diplomatic')),
('D', _('Bandung')),
('DA', _('Kalimantan Selatan')),
('DB', _('Sulawesi Utara Daratan')),
('DC', _('Sulawesi Barat')),
('DD', _('Sulawesi Selatan')),
('DE', _('Maluku')),
('DG', _('Maluku Utara')),
('DH', _('NTT - Timor')),
('DK', _('Bali')),
('DL', _('Sulawesi Utara Kepulauan')),
('DM', _('Gorontalo')),
('DN', _('Sulawesi Tengah')),
('DR', _('NTB - Lombok')),
('DS', _('Papua dan Papua Barat')),
('DT', _('Sulawesi Tenggara')),
('E', _('Cirebon')),
('EA', _('NTB - Sumbawa')),
('EB', _('NTT - Flores')),
('ED', _('NTT - Sumba')),
('F', _('Bogor')),
('G', _('Pekalongan')),
('H', _('Semarang')),
('K', _('Pati')),
('KB', _('Kalimantan Barat')),
('KH', _('Kalimantan Tengah')),
('KT', _('Kalimantan Timur')),
('L', _('Surabaya')),
('M', _('Madura')),
('N', _('Malang')),
('P', _('Jember')),
('R', _('Banyumas')),
('RI', _('Federal Government')),
('S', _('Bojonegoro')),
('T', _('Purwakarta')),
('W', _('Sidoarjo')),
('Z', _('Garut')),
)

View File

@ -1,16 +0,0 @@
"""
UK-specific Form helpers
"""
from __future__ import absolute_import
from django.contrib.localflavor.ie.ie_counties import IE_COUNTY_CHOICES
from django.forms.fields import Select
class IECountySelect(Select):
"""
A Select widget that uses a list of Irish Counties as its choices.
"""
def __init__(self, attrs=None):
super(IECountySelect, self).__init__(attrs, choices=IE_COUNTY_CHOICES)

View File

@ -1,40 +0,0 @@
"""
Sources:
Irish Counties: http://en.wikipedia.org/wiki/Counties_of_Ireland
"""
from django.utils.translation import ugettext_lazy as _
IE_COUNTY_CHOICES = (
('antrim', _('Antrim')),
('armagh', _('Armagh')),
('carlow', _('Carlow')),
('cavan', _('Cavan')),
('clare', _('Clare')),
('cork', _('Cork')),
('derry', _('Derry')),
('donegal', _('Donegal')),
('down', _('Down')),
('dublin', _('Dublin')),
('fermanagh', _('Fermanagh')),
('galway', _('Galway')),
('kerry', _('Kerry')),
('kildare', _('Kildare')),
('kilkenny', _('Kilkenny')),
('laois', _('Laois')),
('leitrim', _('Leitrim')),
('limerick', _('Limerick')),
('longford', _('Longford')),
('louth', _('Louth')),
('mayo', _('Mayo')),
('meath', _('Meath')),
('monaghan', _('Monaghan')),
('offaly', _('Offaly')),
('roscommon', _('Roscommon')),
('sligo', _('Sligo')),
('tipperary', _('Tipperary')),
('tyrone', _('Tyrone')),
('waterford', _('Waterford')),
('westmeath', _('Westmeath')),
('wexford', _('Wexford')),
('wicklow', _('Wicklow')),
)

View File

@ -1,67 +0,0 @@
"""
Israeli-specific form helpers
"""
from __future__ import unicode_literals
import re
from django.core.exceptions import ValidationError
from django.core.validators import EMPTY_VALUES
from django.forms.fields import RegexField, Field, EMPTY_VALUES
from django.utils.checksums import luhn
from django.utils.translation import ugettext_lazy as _
# Israeli ID numbers consist of up to 8 digits followed by a checksum digit.
# Numbers which are shorter than 8 digits are effectively left-zero-padded.
# The checksum digit is occasionally separated from the number by a hyphen,
# and is calculated using the luhn algorithm.
#
# Relevant references:
#
# (hebrew) http://he.wikipedia.org/wiki/%D7%9E%D7%A1%D7%A4%D7%A8_%D7%96%D7%94%D7%95%D7%AA_(%D7%99%D7%A9%D7%A8%D7%90%D7%9C)
# (hebrew) http://he.wikipedia.org/wiki/%D7%A1%D7%A4%D7%A8%D7%AA_%D7%91%D7%99%D7%A7%D7%95%D7%A8%D7%AA
id_number_re = re.compile(r'^(?P<number>\d{1,8})-?(?P<check>\d)$')
class ILPostalCodeField(RegexField):
"""
A form field that validates its input as an Israeli postal code.
Valid form is XXXXX where X represents integer.
"""
default_error_messages = {
'invalid': _('Enter a postal code in the format XXXXX'),
}
def __init__(self, *args, **kwargs):
super(ILPostalCodeField, self).__init__(r'^\d{5}$', *args, **kwargs)
def clean(self, value):
if value not in EMPTY_VALUES:
value = value.replace(" ", "")
return super(ILPostalCodeField, self).clean(value)
class ILIDNumberField(Field):
"""
A form field that validates its input as an Israeli identification number.
Valid form is per the Israeli ID specification.
"""
default_error_messages = {
'invalid': _('Enter a valid ID number.'),
}
def clean(self, value):
value = super(ILIDNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
match = id_number_re.match(value)
if not match:
raise ValidationError(self.error_messages['invalid'])
value = match.group('number') + match.group('check')
if not luhn(value):
raise ValidationError(self.error_messages['invalid'])
return value

View File

@ -1,115 +0,0 @@
"""
India-specific Form helpers.
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.in_.in_states import STATES_NORMALIZED, STATE_CHOICES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, CharField, Select
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
phone_digits_re = re.compile(r"""
(
(?P<std_code> # the std-code group
^0 # all std-codes start with 0
(
(?P<twodigit>\d{2}) | # either two, three or four digits
(?P<threedigit>\d{3}) | # following the 0
(?P<fourdigit>\d{4})
)
)
[-\s] # space or -
(?P<phone_no> # the phone number group
[1-6] # first digit of phone number
(
(?(twodigit)\d{7}) | # 7 more phone digits for 3 digit stdcode
(?(threedigit)\d{6}) | # 6 more phone digits for 4 digit stdcode
(?(fourdigit)\d{5}) # 5 more phone digits for 5 digit stdcode
)
)
)$""", re.VERBOSE)
class INZipCodeField(RegexField):
default_error_messages = {
'invalid': _('Enter a zip code in the format XXXXXX or XXX XXX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(INZipCodeField, self).__init__(r'^\d{3}\s?\d{3}$',
max_length, min_length, *args, **kwargs)
def clean(self, value):
super(INZipCodeField, self).clean(value)
if value in EMPTY_VALUES:
return ''
# Convert to "NNNNNN" if "NNN NNN" given
value = re.sub(r'^(\d{3})\s(\d{3})$', r'\1\2', value)
return value
class INStateField(Field):
"""
A form field that validates its input is a Indian state name or
abbreviation. It normalizes the input to the standard two-letter vehicle
registration abbreviation for the given state or union territory
"""
default_error_messages = {
'invalid': _('Enter an Indian state or territory.'),
}
def clean(self, value):
super(INStateField, self).clean(value)
if value in EMPTY_VALUES:
return ''
try:
value = value.strip().lower()
except AttributeError:
pass
else:
try:
return smart_text(STATES_NORMALIZED[value.strip().lower()])
except KeyError:
pass
raise ValidationError(self.error_messages['invalid'])
class INStateSelect(Select):
"""
A Select widget that uses a list of Indian states/territories as its
choices.
"""
def __init__(self, attrs=None):
super(INStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
class INPhoneNumberField(CharField):
"""
INPhoneNumberField validates that the data is a valid Indian phone number,
including the STD code. It's normalised to 0XXX-XXXXXXX or 0XXX XXXXXXX
format. The first string is the STD code which is a '0' followed by 2-4
digits. The second string is 8 digits if the STD code is 3 digits, 7
digits if the STD code is 4 digits and 6 digits if the STD code is 5
digits. The second string will start with numbers between 1 and 6. The
separator is either a space or a hyphen.
"""
default_error_messages = {
'invalid': _('Phone numbers must be in 02X-8X or 03X-7X or 04X-6X format.'),
}
def clean(self, value):
super(INPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = smart_text(value)
m = phone_digits_re.match(value)
if m:
return '%s' % (value)
raise ValidationError(self.error_messages['invalid'])

View File

@ -1,133 +0,0 @@
"""
A mapping of state misspellings/abbreviations to normalized abbreviations, and
an alphabetical list of states for use as `choices` in a formfield.
This exists in this standalone file so that it's only imported into memory
when explicitly needed.
"""
STATE_CHOICES = (
('KA', 'Karnataka'),
('AP', 'Andhra Pradesh'),
('KL', 'Kerala'),
('TN', 'Tamil Nadu'),
('MH', 'Maharashtra'),
('UP', 'Uttar Pradesh'),
('GA', 'Goa'),
('GJ', 'Gujarat'),
('RJ', 'Rajasthan'),
('HP', 'Himachal Pradesh'),
('JK', 'Jammu and Kashmir'),
('AR', 'Arunachal Pradesh'),
('AS', 'Assam'),
('BR', 'Bihar'),
('CG', 'Chattisgarh'),
('HR', 'Haryana'),
('JH', 'Jharkhand'),
('MP', 'Madhya Pradesh'),
('MN', 'Manipur'),
('ML', 'Meghalaya'),
('MZ', 'Mizoram'),
('NL', 'Nagaland'),
('OR', 'Orissa'),
('PB', 'Punjab'),
('SK', 'Sikkim'),
('TR', 'Tripura'),
('UA', 'Uttarakhand'),
('WB', 'West Bengal'),
# Union Territories
('AN', 'Andaman and Nicobar'),
('CH', 'Chandigarh'),
('DN', 'Dadra and Nagar Haveli'),
('DD', 'Daman and Diu'),
('DL', 'Delhi'),
('LD', 'Lakshadweep'),
('PY', 'Pondicherry'),
)
STATES_NORMALIZED = {
'an': 'AN',
'andaman and nicobar': 'AN',
'andra pradesh': 'AP',
'andrapradesh': 'AP',
'andhrapradesh': 'AP',
'ap': 'AP',
'andhra pradesh': 'AP',
'ar': 'AR',
'arunachal pradesh': 'AR',
'assam': 'AS',
'as': 'AS',
'bihar': 'BR',
'br': 'BR',
'cg': 'CG',
'chattisgarh': 'CG',
'ch': 'CH',
'chandigarh': 'CH',
'daman and diu': 'DD',
'dd': 'DD',
'dl': 'DL',
'delhi': 'DL',
'dn': 'DN',
'dadra and nagar haveli': 'DN',
'ga': 'GA',
'goa': 'GA',
'gj': 'GJ',
'gujarat': 'GJ',
'himachal pradesh': 'HP',
'hp': 'HP',
'hr': 'HR',
'haryana': 'HR',
'jharkhand': 'JH',
'jh': 'JH',
'jammu and kashmir': 'JK',
'jk': 'JK',
'karnataka': 'KA',
'karnatka': 'KA',
'ka': 'KA',
'kerala': 'KL',
'kl': 'KL',
'ld': 'LD',
'lakshadweep': 'LD',
'maharastra': 'MH',
'mh': 'MH',
'maharashtra': 'MH',
'meghalaya': 'ML',
'ml': 'ML',
'mn': 'MN',
'manipur': 'MN',
'madhya pradesh': 'MP',
'mp': 'MP',
'mizoram': 'MZ',
'mizo': 'MZ',
'mz': 'MZ',
'nl': 'NL',
'nagaland': 'NL',
'orissa': 'OR',
'odisa': 'OR',
'orisa': 'OR',
'or': 'OR',
'pb': 'PB',
'punjab': 'PB',
'py': 'PY',
'pondicherry': 'PY',
'rajasthan': 'RJ',
'rajastan': 'RJ',
'rj': 'RJ',
'sikkim': 'SK',
'sk': 'SK',
'tamil nadu': 'TN',
'tn': 'TN',
'tamilnadu': 'TN',
'tamilnad': 'TN',
'tr': 'TR',
'tripura': 'TR',
'ua': 'UA',
'uttarakhand': 'UA',
'up': 'UP',
'uttar pradesh': 'UP',
'westbengal': 'WB',
'bengal': 'WB',
'wb': 'WB',
'west bengal': 'WB'
}

View File

@ -1,86 +0,0 @@
"""
Iceland specific form helpers.
"""
from __future__ import absolute_import, unicode_literals
from django.contrib.localflavor.is_.is_postalcodes import IS_POSTALCODES
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import RegexField
from django.forms.widgets import Select
from django.utils.encoding import smart_text
from django.utils.translation import ugettext_lazy as _
class ISIdNumberField(RegexField):
"""
Icelandic identification number (kennitala). This is a number every citizen
of Iceland has.
"""
default_error_messages = {
'invalid': _('Enter a valid Icelandic identification number. The format is XXXXXX-XXXX.'),
'checksum': _('The Icelandic identification number is not valid.'),
}
def __init__(self, max_length=11, min_length=10, *args, **kwargs):
super(ISIdNumberField, self).__init__(r'^\d{6}(-| )?\d{4}$',
max_length, min_length, *args, **kwargs)
def clean(self, value):
value = super(ISIdNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = self._canonify(value)
if self._validate(value):
return self._format(value)
else:
raise ValidationError(self.error_messages['checksum'])
def _canonify(self, value):
"""
Returns the value as only digits.
"""
return value.replace('-', '').replace(' ', '')
def _validate(self, value):
"""
Takes in the value in canonical form and checks the verifier digit. The
method is modulo 11.
"""
check = [3, 2, 7, 6, 5, 4, 3, 2, 1, 0]
return sum([int(value[i]) * check[i] for i in range(10)]) % 11 == 0
def _format(self, value):
"""
Takes in the value in canonical form and returns it in the common
display format.
"""
return smart_text(value[:6]+'-'+value[6:])
class ISPhoneNumberField(RegexField):
"""
Icelandic phone number. Seven digits with an optional hyphen or space after
the first three digits.
"""
def __init__(self, max_length=8, min_length=7, *args, **kwargs):
super(ISPhoneNumberField, self).__init__(r'^\d{3}(-| )?\d{4}$',
max_length, min_length, *args, **kwargs)
def clean(self, value):
value = super(ISPhoneNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
return value.replace('-', '').replace(' ', '')
class ISPostalCodeSelect(Select):
"""
A Select widget that uses a list of Icelandic postal codes as its choices.
"""
def __init__(self, attrs=None):
super(ISPostalCodeSelect, self).__init__(attrs, choices=IS_POSTALCODES)

View File

@ -1,152 +0,0 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
IS_POSTALCODES = (
('101', '101 Reykjavík'),
('103', '103 Reykjavík'),
('104', '104 Reykjavík'),
('105', '105 Reykjavík'),
('107', '107 Reykjavík'),
('108', '108 Reykjavík'),
('109', '109 Reykjavík'),
('110', '110 Reykjavík'),
('111', '111 Reykjavík'),
('112', '112 Reykjavík'),
('113', '113 Reykjavík'),
('116', '116 Kjalarnes'),
('121', '121 Reykjavík'),
('123', '123 Reykjavík'),
('124', '124 Reykjavík'),
('125', '125 Reykjavík'),
('127', '127 Reykjavík'),
('128', '128 Reykjavík'),
('129', '129 Reykjavík'),
('130', '130 Reykjavík'),
('132', '132 Reykjavík'),
('150', '150 Reykjavík'),
('155', '155 Reykjavík'),
('170', '170 Seltjarnarnes'),
('172', '172 Seltjarnarnes'),
('190', '190 Vogar'),
('200', '200 Kópavogur'),
('201', '201 Kópavogur'),
('202', '202 Kópavogur'),
('203', '203 Kópavogur'),
('210', '210 Garðabær'),
('212', '212 Garðabær'),
('220', '220 Hafnarfjörður'),
('221', '221 Hafnarfjörður'),
('222', '222 Hafnarfjörður'),
('225', '225 Álftanes'),
('230', '230 Reykjanesbær'),
('232', '232 Reykjanesbær'),
('233', '233 Reykjanesbær'),
('235', '235 Keflavíkurflugvöllur'),
('240', '240 Grindavík'),
('245', '245 Sandgerði'),
('250', '250 Garður'),
('260', '260 Reykjanesbær'),
('270', '270 Mosfellsbær'),
('300', '300 Akranes'),
('301', '301 Akranes'),
('302', '302 Akranes'),
('310', '310 Borgarnes'),
('311', '311 Borgarnes'),
('320', '320 Reykholt í Borgarfirði'),
('340', '340 Stykkishólmur'),
('345', '345 Flatey á Breiðafirði'),
('350', '350 Grundarfjörður'),
('355', '355 Ólafsvík'),
('356', '356 Snæfellsbær'),
('360', '360 Hellissandur'),
('370', '370 Búðardalur'),
('371', '371 Búðardalur'),
('380', '380 Reykhólahreppur'),
('400', '400 Ísafjörður'),
('401', '401 Ísafjörður'),
('410', '410 Hnífsdalur'),
('415', '415 Bolungarvík'),
('420', '420 Súðavík'),
('425', '425 Flateyri'),
('430', '430 Suðureyri'),
('450', '450 Patreksfjörður'),
('451', '451 Patreksfjörður'),
('460', '460 Tálknafjörður'),
('465', '465 Bíldudalur'),
('470', '470 Þingeyri'),
('471', '471 Þingeyri'),
('500', '500 Staður'),
('510', '510 Hólmavík'),
('512', '512 Hólmavík'),
('520', '520 Drangsnes'),
('522', '522 Kjörvogur'),
('523', '523 Bær'),
('524', '524 Norðurfjörður'),
('530', '530 Hvammstangi'),
('531', '531 Hvammstangi'),
('540', '540 Blönduós'),
('541', '541 Blönduós'),
('545', '545 Skagaströnd'),
('550', '550 Sauðárkrókur'),
('551', '551 Sauðárkrókur'),
('560', '560 Varmahlíð'),
('565', '565 Hofsós'),
('566', '566 Hofsós'),
('570', '570 Fljót'),
('580', '580 Siglufjörður'),
('600', '600 Akureyri'),
('601', '601 Akureyri'),
('602', '602 Akureyri'),
('603', '603 Akureyri'),
('610', '610 Grenivík'),
('611', '611 Grímsey'),
('620', '620 Dalvík'),
('621', '621 Dalvík'),
('625', '625 Ólafsfjörður'),
('630', '630 Hrísey'),
('640', '640 Húsavík'),
('641', '641 Húsavík'),
('645', '645 Fosshóll'),
('650', '650 Laugar'),
('660', '660 Mývatn'),
('670', '670 Kópasker'),
('671', '671 Kópasker'),
('675', '675 Raufarhöfn'),
('680', '680 Þórshöfn'),
('681', '681 Þórshöfn'),
('685', '685 Bakkafjörður'),
('690', '690 Vopnafjörður'),
('700', '700 Egilsstaðir'),
('701', '701 Egilsstaðir'),
('710', '710 Seyðisfjörður'),
('715', '715 Mjóifjörður'),
('720', '720 Borgarfjörður eystri'),
('730', '730 Reyðarfjörður'),
('735', '735 Eskifjörður'),
('740', '740 Neskaupstaður'),
('750', '750 Fáskrúðsfjörður'),
('755', '755 Stöðvarfjörður'),
('760', '760 Breiðdalsvík'),
('765', '765 Djúpivogur'),
('780', '780 Höfn í Hornafirði'),
('781', '781 Höfn í Hornafirði'),
('785', '785 Öræfi'),
('800', '800 Selfoss'),
('801', '801 Selfoss'),
('802', '802 Selfoss'),
('810', '810 Hveragerði'),
('815', '815 Þorlákshöfn'),
('820', '820 Eyrarbakki'),
('825', '825 Stokkseyri'),
('840', '840 Laugarvatn'),
('845', '845 Flúðir'),
('850', '850 Hella'),
('851', '851 Hella'),
('860', '860 Hvolsvöllur'),
('861', '861 Hvolsvöllur'),
('870', '870 Vík'),
('871', '871 Vík'),
('880', '880 Kirkjubæjarklaustur'),
('900', '900 Vestmannaeyjar'),
('902', '902 Vestmannaeyjar')
)

View File

@ -1,88 +0,0 @@
"""
IT-specific Form helpers
"""
from __future__ import absolute_import, unicode_literals
import re
from django.contrib.localflavor.it.it_province import PROVINCE_CHOICES
from django.contrib.localflavor.it.it_region import REGION_CHOICES
from django.contrib.localflavor.it.util import ssn_check_digit, vat_number_check_digit
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field, RegexField, Select
from django.utils.translation import ugettext_lazy as _
from django.utils.encoding import smart_text
class ITZipCodeField(RegexField):
default_error_messages = {
'invalid': _('Enter a valid zip code.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(ITZipCodeField, self).__init__(r'^\d{5}$',
max_length, min_length, *args, **kwargs)
class ITRegionSelect(Select):
"""
A Select widget that uses a list of IT regions as its choices.
"""
def __init__(self, attrs=None):
super(ITRegionSelect, self).__init__(attrs, choices=REGION_CHOICES)
class ITProvinceSelect(Select):
"""
A Select widget that uses a list of IT provinces as its choices.
"""
def __init__(self, attrs=None):
super(ITProvinceSelect, self).__init__(attrs, choices=PROVINCE_CHOICES)
class ITSocialSecurityNumberField(RegexField):
"""
A form field that validates Italian Social Security numbers (codice fiscale).
For reference see http://www.agenziaentrate.it/ and search for
'Informazioni sulla codificazione delle persone fisiche'.
"""
default_error_messages = {
'invalid': _('Enter a valid Social Security number.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(ITSocialSecurityNumberField, self).__init__(r'^\w{3}\s*\w{3}\s*\w{5}\s*\w{5}$',
max_length, min_length, *args, **kwargs)
def clean(self, value):
value = super(ITSocialSecurityNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
value = re.sub('\s', '', value).upper()
try:
check_digit = ssn_check_digit(value)
except ValueError:
raise ValidationError(self.error_messages['invalid'])
if not value[15] == check_digit:
raise ValidationError(self.error_messages['invalid'])
return value
class ITVatNumberField(Field):
"""
A form field that validates Italian VAT numbers (partita IVA).
"""
default_error_messages = {
'invalid': _('Enter a valid VAT number.'),
}
def clean(self, value):
value = super(ITVatNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
try:
vat_number = int(value)
except ValueError:
raise ValidationError(self.error_messages['invalid'])
vat_number = str(vat_number).zfill(11)
check_digit = vat_number_check_digit(vat_number[0:10])
if not vat_number[10] == check_digit:
raise ValidationError(self.error_messages['invalid'])
return smart_text(vat_number)

View File

@ -1,115 +0,0 @@
# -*- coding: utf-8 -*
from __future__ import unicode_literals
PROVINCE_CHOICES = (
('AG', 'Agrigento'),
('AL', 'Alessandria'),
('AN', 'Ancona'),
('AO', 'Aosta'),
('AR', 'Arezzo'),
('AP', 'Ascoli Piceno'),
('AT', 'Asti'),
('AV', 'Avellino'),
('BA', 'Bari'),
('BT', 'Barletta-Andria-Trani'), # active starting from 2009
('BL', 'Belluno'),
('BN', 'Benevento'),
('BG', 'Bergamo'),
('BI', 'Biella'),
('BO', 'Bologna'),
('BZ', 'Bolzano/Bozen'),
('BS', 'Brescia'),
('BR', 'Brindisi'),
('CA', 'Cagliari'),
('CL', 'Caltanissetta'),
('CB', 'Campobasso'),
('CI', 'Carbonia-Iglesias'),
('CE', 'Caserta'),
('CT', 'Catania'),
('CZ', 'Catanzaro'),
('CH', 'Chieti'),
('CO', 'Como'),
('CS', 'Cosenza'),
('CR', 'Cremona'),
('KR', 'Crotone'),
('CN', 'Cuneo'),
('EN', 'Enna'),
('FM', 'Fermo'), # active starting from 2009
('FE', 'Ferrara'),
('FI', 'Firenze'),
('FG', 'Foggia'),
('FC', 'Forlì-Cesena'),
('FR', 'Frosinone'),
('GE', 'Genova'),
('GO', 'Gorizia'),
('GR', 'Grosseto'),
('IM', 'Imperia'),
('IS', 'Isernia'),
('SP', 'La Spezia'),
('AQ', 'LAquila'),
('LT', 'Latina'),
('LE', 'Lecce'),
('LC', 'Lecco'),
('LI', 'Livorno'),
('LO', 'Lodi'),
('LU', 'Lucca'),
('MC', 'Macerata'),
('MN', 'Mantova'),
('MS', 'Massa-Carrara'),
('MT', 'Matera'),
('VS', 'Medio Campidano'),
('ME', 'Messina'),
('MI', 'Milano'),
('MO', 'Modena'),
('MB', 'Monza e Brianza'), # active starting from 2009
('NA', 'Napoli'),
('NO', 'Novara'),
('NU', 'Nuoro'),
('OG', 'Ogliastra'),
('OT', 'Olbia-Tempio'),
('OR', 'Oristano'),
('PD', 'Padova'),
('PA', 'Palermo'),
('PR', 'Parma'),
('PV', 'Pavia'),
('PG', 'Perugia'),
('PU', 'Pesaro e Urbino'),
('PE', 'Pescara'),
('PC', 'Piacenza'),
('PI', 'Pisa'),
('PT', 'Pistoia'),
('PN', 'Pordenone'),
('PZ', 'Potenza'),
('PO', 'Prato'),
('RG', 'Ragusa'),
('RA', 'Ravenna'),
('RC', 'Reggio Calabria'),
('RE', 'Reggio Emilia'),
('RI', 'Rieti'),
('RN', 'Rimini'),
('RM', 'Roma'),
('RO', 'Rovigo'),
('SA', 'Salerno'),
('SS', 'Sassari'),
('SV', 'Savona'),
('SI', 'Siena'),
('SR', 'Siracusa'),
('SO', 'Sondrio'),
('TA', 'Taranto'),
('TE', 'Teramo'),
('TR', 'Terni'),
('TO', 'Torino'),
('TP', 'Trapani'),
('TN', 'Trento'),
('TV', 'Treviso'),
('TS', 'Trieste'),
('UD', 'Udine'),
('VA', 'Varese'),
('VE', 'Venezia'),
('VB', 'Verbano Cusio Ossola'),
('VC', 'Vercelli'),
('VR', 'Verona'),
('VV', 'Vibo Valentia'),
('VI', 'Vicenza'),
('VT', 'Viterbo'),
)

View File

@ -1,25 +0,0 @@
# -*- coding: utf-8 -*
from __future__ import unicode_literals
REGION_CHOICES = (
('ABR', 'Abruzzo'),
('BAS', 'Basilicata'),
('CAL', 'Calabria'),
('CAM', 'Campania'),
('EMR', 'Emilia-Romagna'),
('FVG', 'Friuli-Venezia Giulia'),
('LAZ', 'Lazio'),
('LIG', 'Liguria'),
('LOM', 'Lombardia'),
('MAR', 'Marche'),
('MOL', 'Molise'),
('PMN', 'Piemonte'),
('PUG', 'Puglia'),
('SAR', 'Sardegna'),
('SIC', 'Sicilia'),
('TOS', 'Toscana'),
('TAA', 'Trentino-Alto Adige'),
('UMB', 'Umbria'),
('VAO', 'Valle dAosta'),
('VEN', 'Veneto'),
)

View File

@ -1,44 +0,0 @@
from django.utils.encoding import smart_text
def ssn_check_digit(value):
"Calculate Italian social security number check digit."
ssn_even_chars = {
'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8,
'9': 9, 'A': 0, 'B': 1, 'C': 2, 'D': 3, 'E': 4, 'F': 5, 'G': 6, 'H': 7,
'I': 8, 'J': 9, 'K': 10, 'L': 11, 'M': 12, 'N': 13, 'O': 14, 'P': 15,
'Q': 16, 'R': 17, 'S': 18, 'T': 19, 'U': 20, 'V': 21, 'W': 22, 'X': 23,
'Y': 24, 'Z': 25
}
ssn_odd_chars = {
'0': 1, '1': 0, '2': 5, '3': 7, '4': 9, '5': 13, '6': 15, '7': 17, '8':
19, '9': 21, 'A': 1, 'B': 0, 'C': 5, 'D': 7, 'E': 9, 'F': 13, 'G': 15,
'H': 17, 'I': 19, 'J': 21, 'K': 2, 'L': 4, 'M': 18, 'N': 20, 'O': 11,
'P': 3, 'Q': 6, 'R': 8, 'S': 12, 'T': 14, 'U': 16, 'V': 10, 'W': 22,
'X': 25, 'Y': 24, 'Z': 23
}
# Chars from 'A' to 'Z'
ssn_check_digits = [chr(x) for x in range(65, 91)]
ssn = value.upper()
total = 0
for i in range(0, 15):
try:
if i % 2 == 0:
total += ssn_odd_chars[ssn[i]]
else:
total += ssn_even_chars[ssn[i]]
except KeyError:
msg = "Character '%(char)s' is not allowed." % {'char': ssn[i]}
raise ValueError(msg)
return ssn_check_digits[total % 26]
def vat_number_check_digit(vat_number):
"Calculate Italian VAT number check digit."
normalized_vat_number = smart_text(vat_number).zfill(10)
total = 0
for i in range(0, 10, 2):
total += int(normalized_vat_number[i])
for i in range(1, 11, 2):
quotient , remainder = divmod(int(normalized_vat_number[i]) * 2, 10)
total += quotient + remainder
return smart_text((10 - total % 10) % 10)

View File

@ -1,39 +0,0 @@
"""
JP-specific Form helpers
"""
from __future__ import absolute_import
from django.contrib.localflavor.jp.jp_prefectures import JP_PREFECTURES
from django.forms.fields import RegexField, Select
from django.utils.translation import ugettext_lazy as _
class JPPostalCodeField(RegexField):
"""
A form field that validates its input is a Japanese postcode.
Accepts 7 digits, with or without a hyphen.
"""
default_error_messages = {
'invalid': _('Enter a postal code in the format XXXXXXX or XXX-XXXX.'),
}
def __init__(self, max_length=None, min_length=None, *args, **kwargs):
super(JPPostalCodeField, self).__init__(r'^\d{3}-\d{4}$|^\d{7}$',
max_length, min_length, *args, **kwargs)
def clean(self, value):
"""
Validates the input and returns a string that contains only numbers.
Returns an empty string for empty values.
"""
v = super(JPPostalCodeField, self).clean(value)
return v.replace('-', '')
class JPPrefectureSelect(Select):
"""
A Select widget that uses a list of Japanese prefectures as its choices.
"""
def __init__(self, attrs=None):
super(JPPrefectureSelect, self).__init__(attrs, choices=JP_PREFECTURES)

View File

@ -1,51 +0,0 @@
from django.utils.translation import ugettext_lazy
JP_PREFECTURES = (
('hokkaido', ugettext_lazy('Hokkaido'),),
('aomori', ugettext_lazy('Aomori'),),
('iwate', ugettext_lazy('Iwate'),),
('miyagi', ugettext_lazy('Miyagi'),),
('akita', ugettext_lazy('Akita'),),
('yamagata', ugettext_lazy('Yamagata'),),
('fukushima', ugettext_lazy('Fukushima'),),
('ibaraki', ugettext_lazy('Ibaraki'),),
('tochigi', ugettext_lazy('Tochigi'),),
('gunma', ugettext_lazy('Gunma'),),
('saitama', ugettext_lazy('Saitama'),),
('chiba', ugettext_lazy('Chiba'),),
('tokyo', ugettext_lazy('Tokyo'),),
('kanagawa', ugettext_lazy('Kanagawa'),),
('yamanashi', ugettext_lazy('Yamanashi'),),
('nagano', ugettext_lazy('Nagano'),),
('niigata', ugettext_lazy('Niigata'),),
('toyama', ugettext_lazy('Toyama'),),
('ishikawa', ugettext_lazy('Ishikawa'),),
('fukui', ugettext_lazy('Fukui'),),
('gifu', ugettext_lazy('Gifu'),),
('shizuoka', ugettext_lazy('Shizuoka'),),
('aichi', ugettext_lazy('Aichi'),),
('mie', ugettext_lazy('Mie'),),
('shiga', ugettext_lazy('Shiga'),),
('kyoto', ugettext_lazy('Kyoto'),),
('osaka', ugettext_lazy('Osaka'),),
('hyogo', ugettext_lazy('Hyogo'),),
('nara', ugettext_lazy('Nara'),),
('wakayama', ugettext_lazy('Wakayama'),),
('tottori', ugettext_lazy('Tottori'),),
('shimane', ugettext_lazy('Shimane'),),
('okayama', ugettext_lazy('Okayama'),),
('hiroshima', ugettext_lazy('Hiroshima'),),
('yamaguchi', ugettext_lazy('Yamaguchi'),),
('tokushima', ugettext_lazy('Tokushima'),),
('kagawa', ugettext_lazy('Kagawa'),),
('ehime', ugettext_lazy('Ehime'),),
('kochi', ugettext_lazy('Kochi'),),
('fukuoka', ugettext_lazy('Fukuoka'),),
('saga', ugettext_lazy('Saga'),),
('nagasaki', ugettext_lazy('Nagasaki'),),
('kumamoto', ugettext_lazy('Kumamoto'),),
('oita', ugettext_lazy('Oita'),),
('miyazaki', ugettext_lazy('Miyazaki'),),
('kagoshima', ugettext_lazy('Kagoshima'),),
('okinawa', ugettext_lazy('Okinawa'),),
)

View File

@ -1,65 +0,0 @@
"""
Kuwait-specific Form helpers
"""
from __future__ import unicode_literals
import re
from datetime import date
from django.core.validators import EMPTY_VALUES
from django.forms import ValidationError
from django.forms.fields import Field
from django.utils.translation import gettext as _
id_re = re.compile(r'^(?P<initial>\d{1})(?P<yy>\d\d)(?P<mm>\d\d)(?P<dd>\d\d)(?P<mid>\d{4})(?P<checksum>\d{1})')
class KWCivilIDNumberField(Field):
"""
Kuwaiti Civil ID numbers are 12 digits, second to seventh digits
represents the person's birthdate.
Checks the following rules to determine the validty of the number:
* The number consist of 12 digits.
* The birthdate of the person is a valid date.
* The calculated checksum equals to the last digit of the Civil ID.
"""
default_error_messages = {
'invalid': _('Enter a valid Kuwaiti Civil ID number'),
}
def has_valid_checksum(self, value):
weight = (2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2)
calculated_checksum = 0
for i in range(11):
calculated_checksum += int(value[i]) * weight[i]
remainder = calculated_checksum % 11
checkdigit = 11 - remainder
if checkdigit != int(value[11]):
return False
return True
def clean(self, value):
super(KWCivilIDNumberField, self).clean(value)
if value in EMPTY_VALUES:
return ''
if not re.match(r'^\d{12}$', value):
raise ValidationError(self.error_messages['invalid'])
match = re.match(id_re, value)
if not match:
raise ValidationError(self.error_messages['invalid'])
gd = match.groupdict()
try:
d = date(int(gd['yy']), int(gd['mm']), int(gd['dd']))
except ValueError:
raise ValidationError(self.error_messages['invalid'])
if not self.has_valid_checksum(value):
raise ValidationError(self.error_messages['invalid'])
return value

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More