forms.py :  » Content-Management-Systems » PyLucid » PyLucid_standalone » django » contrib » localflavor » id » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Content Management Systems » PyLucid 
PyLucid » PyLucid_standalone » django » contrib » localflavor » id » forms.py
"""
ID-specific Form helpers
"""

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
from django.utils.encoding import smart_unicode

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 u''

        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 u'%s' % (value, )


class IDProvinceSelect(Select):
    """
    A Select widget that uses a list of provinces of Indonesia as its
    choices.
    """

    def __init__(self, attrs=None):
        from 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 u''

        phone_number = re.sub(r'[\-\s\(\)]', '', smart_unicode(value))

        if phone_re.search(phone_number):
            return smart_unicode(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):
        from 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):
        super(IDLicensePlateField, self).clean(value)
        if value in EMPTY_VALUES:
            return u''

        plate_number = re.sub(r'\s+', ' ',
            smart_unicode(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.
        from id_choices import LICENSE_PLATE_PREFIX_CHOICES
        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 u''

        value = re.sub(r'[\s.]', '', smart_unicode(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:])
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.