Ticket #9022: usps_fields.diff

File usps_fields.diff, 15.0 KB (added by dougvanhorn, 15 years ago)

US Postal Codes patch

  • django/contrib/localflavor/us/us_states.py

     
    232232    'wyo': 'WY',
    233233    'wyoming': 'WY',
    234234}
     235
     236# These choices should be kept in sync with:
     237#   http://www.usps.com/ncsc/lookups/abbreviations.html
     238US_POSTAL_CODE_CHOICES = (
     239    ('AL', 'Alabama'),
     240    ('AK', 'Alaska'),
     241    ('AS', 'American Samoa'),
     242    ('AZ', 'Arizona'),
     243    ('AR', 'Arkansas'),
     244    ('AA', 'Armed Forces Americas'),
     245    ('AE', 'Armed Forces Europe'),
     246    ('AP', 'Armed Forces Pacific'),
     247    ('CA', 'California'),
     248    ('CO', 'Colorado'),
     249    ('CT', 'Connecticut'),
     250    ('DE', 'Delaware'),
     251    ('DC', 'District of Columbia'),
     252    ('FM', 'Federated States of Micronesia'),
     253    ('FL', 'Florida'),
     254    ('GA', 'Georgia'),
     255    ('GU', 'Guam'),
     256    ('HI', 'Hawaii'),
     257    ('ID', 'Idaho'),
     258    ('IL', 'Illinois'),
     259    ('IN', 'Indiana'),
     260    ('IA', 'Iowa'),
     261    ('KS', 'Kansas'),
     262    ('KY', 'Kentucky'),
     263    ('LA', 'Louisiana'),
     264    ('ME', 'Maine'),
     265    ('MH', 'Marshall Islands'),
     266    ('MD', 'Maryland'),
     267    ('MA', 'Massachusetts'),
     268    ('MI', 'Michigan'),
     269    ('MN', 'Minnesota'),
     270    ('MS', 'Mississippi'),
     271    ('MO', 'Missouri'),
     272    ('MT', 'Montana'),
     273    ('NE', 'Nebraska'),
     274    ('NV', 'Nevada'),
     275    ('NH', 'New Hampshire'),
     276    ('NJ', 'New Jersey'),
     277    ('NM', 'New Mexico'),
     278    ('NY', 'New York'),
     279    ('NC', 'North Carolina'),
     280    ('ND', 'North Dakota'),
     281    ('MP', 'Northern Mariana Islands'),
     282    ('OH', 'Ohio'),
     283    ('OK', 'Oklahoma'),
     284    ('OR', 'Oregon'),
     285    ('PW', 'Palau'),
     286    ('PA', 'Pennsylvania'),
     287    ('PR', 'Puerto Rico'),
     288    ('RI', 'Rhode Island'),
     289    ('SC', 'South Carolina'),
     290    ('SD', 'South Dakota'),
     291    ('TN', 'Tennessee'),
     292    ('TX', 'Texas'),
     293    ('UT', 'Utah'),
     294    ('VT', 'Vermont'),
     295    ('VI', 'Virgin Islands'),
     296    ('VA', 'Virginia'),
     297    ('WA', 'Washington'),
     298    ('WV', 'West Virginia'),
     299    ('WI', 'Wisconsin'),
     300    ('WY', 'Wyoming'),
     301)
     302
     303US_POSTAL_CODES_NORMALIZED = {
     304    'aa': 'AA',
     305    'ae': 'AE',
     306    'ak': 'AK',
     307    'al': 'AL',
     308    'ala': 'AL',
     309    'alabama': 'AL',
     310    'alaska': 'AK',
     311    'american samao': 'AS',
     312    'american samoa': 'AS',
     313    'ap': 'AP',
     314    'ar': 'AR',
     315    'ariz': 'AZ',
     316    'arizona': 'AZ',
     317    'ark': 'AR',
     318    'arkansas': 'AR',
     319    'armed forces africa': 'AE',
     320    'armed forces americas': 'AA',
     321    'armed forces europe': 'AE',
     322    'armed forces pacific': 'AP',
     323    'armed forces canada': 'AE',
     324    'armed forces middle east': 'AE',
     325    'as': 'AS',
     326    'az': 'AZ',
     327    'ca': 'CA',
     328    'calf': 'CA',
     329    'calif': 'CA',
     330    'california': 'CA',
     331    'co': 'CO',
     332    'colo': 'CO',
     333    'colorado': 'CO',
     334    'conn': 'CT',
     335    'connecticut': 'CT',
     336    'ct': 'CT',
     337    'dc': 'DC',
     338    'de': 'DE',
     339    'del': 'DE',
     340    'delaware': 'DE',
     341    'deleware': 'DE',
     342    'district of columbia': 'DC',
     343    'federated states of micronesia': 'FM',
     344    'fl': 'FL',
     345    'fla': 'FL',
     346    'florida': 'FL',
     347    'fm': 'FM',
     348    'ga': 'GA',
     349    'georgia': 'GA',
     350    'gu': 'GU',
     351    'guam': 'GU',
     352    'hawaii': 'HI',
     353    'hi': 'HI',
     354    'ia': 'IA',
     355    'id': 'ID',
     356    'idaho': 'ID',
     357    'il': 'IL',
     358    'ill': 'IL',
     359    'illinois': 'IL',
     360    'in': 'IN',
     361    'ind': 'IN',
     362    'indiana': 'IN',
     363    'iowa': 'IA',
     364    'kan': 'KS',
     365    'kans': 'KS',
     366    'kansas': 'KS',
     367    'kentucky': 'KY',
     368    'ks': 'KS',
     369    'ky': 'KY',
     370    'la': 'LA',
     371    'louisiana': 'LA',
     372    'ma': 'MA',
     373    'maine': 'ME',
     374    'marianas islands': 'MP',
     375    'marianas islands of the pacific': 'MP',
     376    'marinas islands of the pacific': 'MP',
     377    'marshall islands': 'MH',
     378    'maryland': 'MD',
     379    'mass': 'MA',
     380    'massachusetts': 'MA',
     381    'massachussetts': 'MA',
     382    'md': 'MD',
     383    'me': 'ME',
     384    'mh': 'MH',
     385    'mi': 'MI',
     386    'mich': 'MI',
     387    'michigan': 'MI',
     388    'micronesia': 'FM',
     389    'minn': 'MN',
     390    'minnesota': 'MN',
     391    'miss': 'MS',
     392    'mississippi': 'MS',
     393    'missouri': 'MO',
     394    'mn': 'MN',
     395    'mo': 'MO',
     396    'mont': 'MT',
     397    'montana': 'MT',
     398    'mp': 'MP',
     399    'ms': 'MS',
     400    'mt': 'MT',
     401    'n d': 'ND',
     402    'n dak': 'ND',
     403    'n h': 'NH',
     404    'n j': 'NJ',
     405    'n m': 'NM',
     406    'n mex': 'NM',
     407    'nc': 'NC',
     408    'nd': 'ND',
     409    'ne': 'NE',
     410    'neb': 'NE',
     411    'nebr': 'NE',
     412    'nebraska': 'NE',
     413    'nev': 'NV',
     414    'nevada': 'NV',
     415    'new hampshire': 'NH',
     416    'new jersey': 'NJ',
     417    'new mexico': 'NM',
     418    'new york': 'NY',
     419    'nh': 'NH',
     420    'nj': 'NJ',
     421    'nm': 'NM',
     422    'nmex': 'NM',
     423    'north carolina': 'NC',
     424    'north dakota': 'ND',
     425    'northern mariana islands': 'MP',
     426    'nv': 'NV',
     427    'ny': 'NY',
     428    'oh': 'OH',
     429    'ohio': 'OH',
     430    'ok': 'OK',
     431    'okla': 'OK',
     432    'oklahoma': 'OK',
     433    'or': 'OR',
     434    'ore': 'OR',
     435    'oreg': 'OR',
     436    'oregon': 'OR',
     437    'pa': 'PA',
     438    'palau': 'PW',
     439    'penn': 'PA',
     440    'pennsylvania': 'PA',
     441    'pr': 'PR',
     442    'puerto rico': 'PR',
     443    'pw': 'PW',
     444    'rhode island': 'RI',
     445    'ri': 'RI',
     446    's dak': 'SD',
     447    'sc': 'SC',
     448    'sd': 'SD',
     449    'sdak': 'SD',
     450    'south carolina': 'SC',
     451    'south dakota': 'SD',
     452    'tenn': 'TN',
     453    'tennessee': 'TN',
     454    'territory of hawaii': 'HI',
     455    'tex': 'TX',
     456    'texas': 'TX',
     457    'tn': 'TN',
     458    'tx': 'TX',
     459    'us virgin islands': 'VI',
     460    'usvi': 'VI',
     461    'ut': 'UT',
     462    'utah': 'UT',
     463    'va': 'VA',
     464    'vermont': 'VT',
     465    'vi': 'VI',
     466    'viginia': 'VA',
     467    'virgin islands': 'VI',
     468    'virgina': 'VA',
     469    'virginia': 'VA',
     470    'vt': 'VT',
     471    'w va': 'WV',
     472    'wa': 'WA',
     473    'wash': 'WA',
     474    'washington': 'WA',
     475    'west virginia': 'WV',
     476    'wi': 'WI',
     477    'wis': 'WI',
     478    'wisc': 'WI',
     479    'wisconsin': 'WI',
     480    'wv': 'WV',
     481    'wva': 'WV',
     482    'wy': 'WY',
     483    'wyo': 'WY',
     484    'wyoming': 'WY',
     485}
  • django/contrib/localflavor/us/models.py

     
    1717        defaults.update(kwargs)
    1818        return super(USStateField, self).formfield(**defaults)
    1919
     20class USPostalCodeField(Field):
     21    """
     22    State field supporting valid USPS two-letter codes.
     23    """
     24    def get_internal_type(self):
     25        return "USPostalCodeField"
     26       
     27    def db_type(self):
     28        if settings.DATABASE_ENGINE == 'oracle':
     29            return 'CHAR(2)'
     30        else:
     31            return 'varchar(2)'
     32   
     33    def formfield(self, **kwargs):
     34        from django.contrib.localflavor.us.forms import USPostalCodeSelect
     35        defaults = {'widget': USPostalCodeSelect}
     36        defaults.update(kwargs)
     37        return super(USPostalCodeField, self).formfield(**defaults)
     38
    2039class PhoneNumberField(Field):
    2140    def get_internal_type(self):
    2241        return "PhoneNumberField"
  • django/contrib/localflavor/us/forms.py

     
    110110    def __init__(self, attrs=None):
    111111        from us_states import STATE_CHOICES
    112112        super(USStateSelect, self).__init__(attrs, choices=STATE_CHOICES)
     113
     114class USPostalCodeField(Field):
     115    """
     116    A form field that validates its input is a US Postal Code state name or abbreviation.
     117    It normalizes the input to the standard two-leter postal service
     118    abbreviation for the given state.
     119    """
     120    default_error_messages = {
     121        'invalid': u'Enter a U.S. state or territory.',
     122    }
     123
     124    def clean(self, value):
     125        from us_states import US_POSTAL_CODES_NORMALIZED
     126        super(USPostalCodeField, self).clean(value)
     127        if value in EMPTY_VALUES:
     128            return u''
     129        try:
     130            value = value.strip().lower()
     131        except AttributeError:
     132            pass
     133        else:
     134            try:
     135                return US_POSTAL_CODES_NORMALIZED[value.strip().lower()].decode('ascii')
     136            except KeyError:
     137                pass
     138        raise ValidationError(self.error_messages['invalid'])
     139
     140class USPostalCodeSelect(Select):
     141    """
     142    A Select widget that uses a list of USPS postal codes as its choices.
     143    """
     144    def __init__(self, attrs=None):
     145        from us_states import US_POSTAL_CODE_CHOICES
     146        super(USPostalCodeSelect, self).__init__(attrs, choices=US_POSTAL_CODE_CHOICES)
  • tests/regressiontests/forms/localflavor/us.py

     
    243243<option value="WY">Wyoming</option>
    244244</select>
    245245
     246# USPostalCodeField ################################################################
     247
     248USPostalCodeField validates that the data is either an abbreviation or name of a
     249USPS postal code.
     250>>> from django.contrib.localflavor.us.forms import USPostalCodeField
     251>>> f = USPostalCodeField()
     252>>> f.clean('mo')
     253u'MO'
     254>>> f.clean('MO')
     255u'MO'
     256>>> f.clean('mIssouri')
     257u'MO'
     258>>> f.clean('  mIssouri ')
     259u'MO'
     260>>> f.clean(63303)
     261Traceback (most recent call last):
     262...
     263ValidationError: [u'Enter a U.S. state or territory.']
     264>>> f.clean(None)
     265Traceback (most recent call last):
     266...
     267ValidationError: [u'This field is required.']
     268>>> f.clean('')
     269Traceback (most recent call last):
     270...
     271ValidationError: [u'This field is required.']
     272
     273>>> f = USPostalCodeField(required=False)
     274>>> f.clean('mo')
     275u'MO'
     276>>> f.clean('MO')
     277u'MO'
     278>>> f.clean('mIssouri')
     279u'MO'
     280>>> f.clean('  mIssouri ')
     281u'MO'
     282>>> f.clean(63303)
     283Traceback (most recent call last):
     284...
     285ValidationError: [u'Enter a U.S. state or territory.']
     286>>> f.clean(None)
     287u''
     288>>> f.clean('')
     289u''
     290
     291# USPostalCodeSelect ###############################################################
     292
     293USPostalCodeSelect is a Select widget that uses a list of USPS postal codes
     294as its choices.
     295>>> from django.contrib.localflavor.us.forms import USPostalCodeSelect
     296>>> w = USPostalCodeSelect()
     297>>> print w.render('state', 'MO')
     298<select name="state">
     299<option value="AL">Alabama</option>
     300<option value="AK">Alaska</option>
     301<option value="AS">American Samoa</option>
     302<option value="AZ">Arizona</option>
     303<option value="AR">Arkansas</option>
     304<option value="AA">Armed Forces Americas</option>
     305<option value="AE">Armed Forces Europe</option>
     306<option value="AP">Armed Forces Pacific</option>
     307<option value="CA">California</option>
     308<option value="CO">Colorado</option>
     309<option value="CT">Connecticut</option>
     310<option value="DE">Delaware</option>
     311<option value="DC">District of Columbia</option>
     312<option value="FM">Federated States of Micronesia</option>
     313<option value="FL">Florida</option>
     314<option value="GA">Georgia</option>
     315<option value="GU">Guam</option>
     316<option value="HI">Hawaii</option>
     317<option value="ID">Idaho</option>
     318<option value="IL">Illinois</option>
     319<option value="IN">Indiana</option>
     320<option value="IA">Iowa</option>
     321<option value="KS">Kansas</option>
     322<option value="KY">Kentucky</option>
     323<option value="LA">Louisiana</option>
     324<option value="ME">Maine</option>
     325<option value="MH">Marshall Islands</option>
     326<option value="MD">Maryland</option>
     327<option value="MA">Massachusetts</option>
     328<option value="MI">Michigan</option>
     329<option value="MN">Minnesota</option>
     330<option value="MS">Mississippi</option>
     331<option value="MO" selected="selected">Missouri</option>
     332<option value="MT">Montana</option>
     333<option value="NE">Nebraska</option>
     334<option value="NV">Nevada</option>
     335<option value="NH">New Hampshire</option>
     336<option value="NJ">New Jersey</option>
     337<option value="NM">New Mexico</option>
     338<option value="NY">New York</option>
     339<option value="NC">North Carolina</option>
     340<option value="ND">North Dakota</option>
     341<option value="MP">Northern Mariana Islands</option>
     342<option value="OH">Ohio</option>
     343<option value="OK">Oklahoma</option>
     344<option value="OR">Oregon</option>
     345<option value="PW">Palau</option>
     346<option value="PA">Pennsylvania</option>
     347<option value="PR">Puerto Rico</option>
     348<option value="RI">Rhode Island</option>
     349<option value="SC">South Carolina</option>
     350<option value="SD">South Dakota</option>
     351<option value="TN">Tennessee</option>
     352<option value="TX">Texas</option>
     353<option value="UT">Utah</option>
     354<option value="VT">Vermont</option>
     355<option value="VI">Virgin Islands</option>
     356<option value="VA">Virginia</option>
     357<option value="WA">Washington</option>
     358<option value="WV">West Virginia</option>
     359<option value="WI">Wisconsin</option>
     360<option value="WY">Wyoming</option>
     361</select>
     362
    246363# USSocialSecurityNumberField #################################################
    247364>>> from django.contrib.localflavor.us.forms import USSocialSecurityNumberField
    248365>>> f = USSocialSecurityNumberField()
  • tests/regressiontests/serializers_regress/tests.py

     
    220220    (data_obj, 180, USStateData, "MA"),
    221221    (data_obj, 181, USStateData, None),
    222222    (data_obj, 182, USStateData, ""),
     223    (data_obj, 183, USPostalCodeData, "MO"),
     224    (data_obj, 184, USPostalCodeData, None),
     225    (data_obj, 185, USPostalCodeData, ""),
    223226    (data_obj, 190, XMLData, "<foo></foo>"),
    224227    (data_obj, 191, XMLData, None),
    225228    (data_obj, 192, XMLData, ""),
     
    313316# The end."""),
    314317#    (pk_obj, 770, TimePKData, datetime.time(10,42,37)),
    315318    (pk_obj, 780, USStatePKData, "MA"),
     319    (pk_obj, 781, USPostalCodePKData, "MO"),
    316320#     (pk_obj, 790, XMLPKData, "<foo></foo>"),
    317321
    318322    (data_obj, 800, AutoNowDateTimeData, datetime.datetime(2006,6,16,10,42,37)),
  • tests/regressiontests/serializers_regress/models.py

     
    88from django.db import models
    99from django.contrib.contenttypes import generic
    1010from django.contrib.contenttypes.models import ContentType
    11 from django.contrib.localflavor.us.models import USStateField, PhoneNumberField
     11from django.contrib.localflavor.us.models import USStateField, USPostalCodeField, PhoneNumberField
    1212
    1313# The following classes are for testing basic data
    1414# marshalling, including NULL values, where allowed.
     
    7676class USStateData(models.Model):
    7777    data = USStateField(null=True)
    7878
     79class USPostalCodeData(models.Model):
     80    data = USPostalCodeField(null=True)
     81
    7982class XMLData(models.Model):
    8083    data = models.XMLField(null=True)
    8184
     
    212215class USStatePKData(models.Model):
    213216    data = USStateField(primary_key=True)
    214217
     218class USPostalCodePKData(models.Model):
     219    data = USPostalCodeField(primary_key=True)
     220
    215221# class XMLPKData(models.Model):
    216222#     data = models.XMLField(primary_key=True)
Back to Top