|
1 """ |
|
2 UK-specific Form helpers |
|
3 """ |
|
4 |
|
5 import re |
|
6 |
|
7 from django.newforms.fields import CharField, Select |
|
8 from django.newforms import ValidationError |
|
9 from django.utils.translation import ugettext |
|
10 |
|
11 class UKPostcodeField(CharField): |
|
12 """ |
|
13 A form field that validates its input is a UK postcode. |
|
14 |
|
15 The regular expression used is sourced from the schema for British Standard |
|
16 BS7666 address types: http://www.govtalk.gov.uk/gdsc/schemas/bs7666-v2-0.xsd |
|
17 |
|
18 The value is uppercased and a space added in the correct place, if required. |
|
19 """ |
|
20 default_error_messages = { |
|
21 'invalid': ugettext(u'Enter a valid postcode.'), |
|
22 } |
|
23 outcode_pattern = '[A-PR-UWYZ]([0-9]{1,2}|([A-HIK-Y][0-9](|[0-9]|[ABEHMNPRVWXY]))|[0-9][A-HJKSTUW])' |
|
24 incode_pattern = '[0-9][ABD-HJLNP-UW-Z]{2}' |
|
25 postcode_regex = re.compile(r'^(GIR 0AA|%s %s)$' % (outcode_pattern, incode_pattern)) |
|
26 space_regex = re.compile(r' *(%s)$' % incode_pattern) |
|
27 |
|
28 def clean(self, value): |
|
29 value = super(UKPostcodeField, self).clean(value) |
|
30 if value == u'': |
|
31 return value |
|
32 postcode = value.upper().strip() |
|
33 # Put a single space before the incode (second part). |
|
34 postcode = self.space_regex.sub(r' \1', postcode) |
|
35 if not self.postcode_regex.search(postcode): |
|
36 raise ValidationError(self.default_error_messages['invalid']) |
|
37 return postcode |
|
38 |
|
39 class UKCountySelect(Select): |
|
40 """ |
|
41 A Select widget that uses a list of UK Counties/Regions as its choices. |
|
42 """ |
|
43 def __init__(self, attrs=None): |
|
44 from uk_regions import UK_REGION_CHOICES |
|
45 super(UKCountySelect, self).__init__(attrs, choices=UK_REGION_CHOICES) |
|
46 |
|
47 class UKNationSelect(Select): |
|
48 """ |
|
49 A Select widget that uses a list of UK Nations as its choices. |
|
50 """ |
|
51 def __init__(self, attrs=None): |
|
52 from uk_regions import UK_NATIONS_CHOICES |
|
53 super(UKNationSelect, self).__init__(attrs, choices=UK_NATIONS_CHOICES) |