Ticket #5670: ukpostcodefield2.diff

File ukpostcodefield2.diff, 3.8 KB (added by scott@…, 8 years ago)

New patch against trunk (includes tests)

  • django/contrib/localflavor/uk/forms.py

     
    11"""
    22UK-specific Form helpers
    33"""
     4import re
    45
    5 from django.newforms.fields import RegexField, Select
     6from django.newforms.fields import CharField, Select
     7from django.newforms import ValidationError
    68from django.utils.translation import ugettext
    79
    8 class UKPostcodeField(RegexField):
     10class UKPostcodeField(CharField):
    911    """
    1012    A form field that validates its input is a UK postcode.
     13   
     14    Uppercases the value and adds space in correct place if required.
    1115
    1216    The regular expression used is sourced from the schema for British Standard
    1317    BS7666 address types: http://www.govtalk.gov.uk/gdsc/schemas/bs7666-v2-0.xsd
    1418    """
    15     def __init__(self, *args, **kwargs):
    16         super(UKPostcodeField, self).__init__(r'^(GIR 0AA|[A-PR-UWYZ]([0-9]{1,2}|([A-HIK-Y][0-9](|[0-9]|[ABEHMNPRVWXY]))|[0-9][A-HJKSTUW]) [0-9][ABD-HJLNP-UW-Z]{2})$',
    17             max_length=None, min_length=None,
    18             error_message=ugettext(u'Enter a postcode. A space is required between the two postcode parts.'),
    19             *args, **kwargs)
     19    OUTCODE_PATTERN = '[A-PR-UWYZ]([0-9]{1,2}|([A-HIK-Y][0-9](|[0-9]|[ABEHMNPRVWXY]))|[0-9][A-HJKSTUW])'
     20    INCODE_PATTERN = '[0-9][ABD-HJLNP-UW-Z]{2}'
     21    POSTCODE_REGEX = re.compile(r'^(GIR 0AA|%s %s)$' % (OUTCODE_PATTERN, INCODE_PATTERN))
     22    SPACE_REGEX = re.compile(r' *(%s)$' % INCODE_PATTERN)
    2023
     24    def clean(self, value):
     25        value = super(UKPostcodeField, self).clean(value)
     26        if value == u'':
     27            return value
     28        postcode = value.upper().strip()
     29        # Put a single space before the incode (second part).
     30        postcode = self.SPACE_REGEX.sub(r' \1', postcode)
     31        if not self.POSTCODE_REGEX.search(postcode):
     32            raise ValidationError(ugettext(u'Enter a valid postcode.'))
     33        return postcode
     34
    2135class UKCountySelect(Select):
    2236    """
    2337    A Select widget that uses a list of UK Counties/Regions as its choices.
  • tests/regressiontests/forms/localflavor/uk.py

     
    1212>>> f.clean('GIR 0AA')
    1313u'GIR 0AA'
    1414>>> f.clean('BT324PX')
     15u'BT32 4PX'
     16>>> f.clean('1NV 4L1D')
    1517Traceback (most recent call last):
    1618...
    17 ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
    18 >>> f.clean('1NV 4L1D')
     19ValidationError: [u'Enter a valid postcode.']
     20>>> f.clean('1NV4L1D')
    1921Traceback (most recent call last):
    2022...
    21 ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
     23ValidationError: [u'Enter a valid postcode.']
    2224>>> f.clean(None)
    2325Traceback (most recent call last):
    2426...
     
    2729Traceback (most recent call last):
    2830...
    2931ValidationError: [u'This field is required.']
    30 
     32>>> f.clean(' so11aa ')
     33u'SO1 1AA'
     34>>> f.clean(' so1  1aa ')
     35u'SO1 1AA'
     36>>> f.clean('G2 3wt')
     37u'G2 3WT'
     38>>> f.clean('EC1A 1BB')
     39u'EC1A 1BB'
     40>>> f.clean('Ec1a1BB')
     41u'EC1A 1BB'
     42>>> f.clean(' b0gUS')
     43Traceback (most recent call last):
     44...
     45ValidationError: [u'Enter a valid postcode.']
    3146>>> f = UKPostcodeField(required=False)
    3247>>> f.clean('BT32 4PX')
    3348u'BT32 4PX'
     
    3651>>> f.clean('1NV 4L1D')
    3752Traceback (most recent call last):
    3853...
    39 ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
     54ValidationError: [u'Enter a valid postcode.']
    4055>>> f.clean('BT324PX')
    41 Traceback (most recent call last):
    42 ...
    43 ValidationError: [u'Enter a postcode. A space is required between the two postcode parts.']
     56u'BT32 4PX'
    4457>>> f.clean(None)
    4558u''
    4659>>> f.clean('')
Back to Top