Index: django/contrib/localflavor/au/au_states.py
===================================================================
--- django/contrib/localflavor/au/au_states.py	(revision 0)
+++ django/contrib/localflavor/au/au_states.py	(revision 0)
@@ -0,0 +1,17 @@
+"""
+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'),
+)
Index: django/contrib/localflavor/au/__init__.py
===================================================================
Index: django/contrib/localflavor/au/forms.py
===================================================================
--- django/contrib/localflavor/au/forms.py	(revision 0)
+++ django/contrib/localflavor/au/forms.py	(revision 0)
@@ -0,0 +1,44 @@
+"""
+Australian-specific Form helpers
+"""
+
+from django.newforms import ValidationError
+from django.newforms.fields import Field, RegexField, Select, EMPTY_VALUES
+from django.newforms.util import smart_unicode
+from django.utils.translation import gettext
+import re
+
+PHONE_DIGITS_RE = re.compile(r'^(\d{10})$')
+
+class AUPostCodeField(RegexField):
+    """Australian post code field."""
+    def __init__(self, *args, **kwargs):
+        super(AUPostCodeField, self).__init__(r'^\d{4}$',
+            max_length=None, min_length=None,
+            error_message=gettext(u'Enter a post code in the format XXXX.'),
+            *args, **kwargs)
+
+class AUPhoneNumberField(Field):
+    """Australian phone number field."""
+    def clean(self, value):
+        """Validate a phone number. Strips parentheses, whitespace and
+        hyphens.
+        """
+        super(AUPhoneNumberField, self).clean(value)
+        if value in EMPTY_VALUES:
+            return u''
+        value = re.sub('(\(|\)|\s+|-)', '', smart_unicode(value))
+        phone_match = PHONE_DIGITS_RE.search(value)
+        if phone_match:
+            return u'%s' % phone_match.group(1)
+        raise ValidationError(u'Phone numbers must consist of 10 digits.' \
+            u' Parentheses, white space and hyphens are allowed.')
+
+class AUStateSelect(Select):
+    """
+    A Select widget that uses a list of Australian states/territories as its
+    choices.
+    """
+    def __init__(self, attrs=None):
+        from au_states import STATE_CHOICES # relative import
+        super(AUStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
Index: tests/regressiontests/forms/localflavor.py
===================================================================
--- tests/regressiontests/forms/localflavor.py	(revision 4940)
+++ tests/regressiontests/forms/localflavor.py	(working copy)
@@ -882,4 +882,122 @@
 Traceback (most recent call last):
 ...
 ValidationError: [u'Enter a valid German identity card number in XXXXXXXXXXX-XXXXXXX-XXXXXXX-X format.']
+
+## AUPostCodeField ##########################################################
+
+A field that accepts a four digit Australian post code.
+
+>>> from django.contrib.localflavor.au.forms import AUPostCodeField
+>>> f = AUPostCodeField()
+>>> f.clean('1234')
+u'1234'
+>>> f.clean('2000')
+u'2000'
+>>> f.clean('abcd')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a post code in the format XXXX.']
+>>> f.clean('20001')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a post code in the format XXXX.']
+>>> f.clean(None)
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+
+>>> f = AUPostCodeField(required=False)
+>>> f.clean('1234')
+u'1234'
+>>> f.clean('2000')
+u'2000'
+>>> f.clean('abcd')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a post code in the format XXXX.']
+>>> f.clean('20001')
+Traceback (most recent call last):
+...
+ValidationError: [u'Enter a post code in the format XXXX.']
+>>> f.clean(None)
+u''
+>>> f.clean('')
+u''
+
+## AUPhoneNumberField ########################################################
+
+A field that accepts a 10 digit Australian phone number.
+llows spaces and parentheses around area code.
+
+>>> from django.contrib.localflavor.au.forms import AUPhoneNumberField
+>>> f = AUPhoneNumberField()
+>>> f.clean('1234567890')
+u'1234567890'
+>>> f.clean('0213456789')
+u'0213456789'
+>>> f.clean('02 13 45 67 89')
+u'0213456789'
+>>> f.clean('(02) 1345 6789')
+u'0213456789'
+>>> f.clean('123')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must consist of 10 digits. Parentheses, white space and hyphens are allowed.']
+>>> f.clean('1800DJANGO')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must consist of 10 digits. Parentheses, white space and hyphens are allowed.']
+>>> f.clean(None)
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+>>> f.clean('')
+Traceback (most recent call last):
+...
+ValidationError: [u'This field is required.']
+
+>>> f = AUPhoneNumberField(required=False)
+>>> f.clean('1234567890')
+u'1234567890'
+>>> f.clean('0213456789')
+u'0213456789'
+>>> f.clean('02 13 45 67 89')
+u'0213456789'
+>>> f.clean('(02) 1345 6789')
+u'0213456789'
+>>> f.clean('123')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must consist of 10 digits. Parentheses, white space and hyphens are allowed.']
+>>> f.clean('1800DJANGO')
+Traceback (most recent call last):
+...
+ValidationError: [u'Phone numbers must consist of 10 digits. Parentheses, white space and hyphens are allowed.']
+>>> f.clean(None)
+u''
+>>> f.clean('')
+u''
+
+## AUStateSelect #############################################################
+
+AUStateSelect is a Select widget that uses a list of Australian
+states/territories as its choices.
+
+>>> from django.contrib.localflavor.au.forms import AUStateSelect
+>>> f = AUStateSelect()
+>>> print f.render('state', 'NSW')
+<select name="state">
+<option value="ACT">Australian Capital Territory</option>
+<option value="NSW" selected="selected">New South Wales</option>
+<option value="NT">Northern Territory</option>
+<option value="QLD">Queensland</option>
+<option value="SA">South Australia</option>
+<option value="TAS">Tasmania</option>
+<option value="VIC">Victoria</option>
+<option value="WA">Western Australia</option>
+</select>
 """
Index: AUTHORS
===================================================================
--- AUTHORS	(revision 4940)
+++ AUTHORS	(working copy)
@@ -88,6 +88,7 @@
     Dirk Eschler <dirk.eschler@gmx.net>
     Marc Fargas <telenieko@telenieko.com>
     favo@exoweb.net
+    Matthew Flanagan <http://wadofstuff.blogspot.com>
     Eric Floehr <eric@intellovations.com>
     Jorge Gajon <gajon@gajon.org>
     gandalf@owca.info
