Initial Revision
authorJustin Bronn <jbronn@geodjango.org>
Sun May 11 17:36:25 2008 -0700 (4 years ago)
changeset 0ff88be78a080
child 1 9af8560dc829
Initial Revision

A rebuild from previous efforts.
__init__.py
census/__init__.py
census/admin.py
census/load.py
census/models.py
manage.py
settings.py
tabc/__init__.py
tabc/load.py
tabc/models.py
tabc/rebuild.py
tabc/views.py
texas/__init__.py
texas/load.py
texas/models.py
texas/views.py
urls.py
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/census/__init__.py	Sun May 11 17:36:25 2008 -0700
     1.3 @@ -0,0 +1,1 @@
     1.4 +from models import County, State
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/census/admin.py	Sun May 11 17:36:25 2008 -0700
     2.3 @@ -0,0 +1,11 @@
     2.4 +from django.contrib.gis import admin
     2.5 +
     2.6 +class CountyAdmin(admin.OSMGeoAdmin):
     2.7 +    list_display = ('name', 'state', 'fips')
     2.8 +    search_fields = ('name', 'state__name', 'fips')
     2.9 +    ordering = ('name',)
    2.10 +
    2.11 +class StateAdmin(admin.OSMGeoAdmin):
    2.12 +    list_display = ('name', 'fips')
    2.13 +    search_fields = ('name', 'fips')
    2.14 +    ordering = ('name',)
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/census/load.py	Sun May 11 17:36:25 2008 -0700
     3.3 @@ -0,0 +1,38 @@
     3.4 +import os
     3.5 +from django.conf import settings
     3.6 +from django.contrib.gis.gdal import SpatialReference
     3.7 +from django.contrib.gis.utils import LayerMapping, add_postgis_srs
     3.8 +from models import County, State
     3.9 +
    3.10 +# County mapping & shapefile
    3.11 +co_mapping = {'state' : {'fips' : 'STATE'}, # Maps to `state` ForeignKey.
    3.12 +              'fips' : 'COUNTY',
    3.13 +              'name' : 'NAME',
    3.14 +              'mpoly' : 'MULTIPOLYGON',
    3.15 +              }
    3.16 +# http://www.census.gov/geo/cob/bdy/co/co00shp/co99_d00_shp.zip
    3.17 +co_shp = os.path.join(settings.GIS_DATA_DIR, 'census/county/co99_d00.shp')
    3.18 +
    3.19 +# State mapping & shapefile.
    3.20 +st_mapping = {'fips' : 'STATE',
    3.21 +              'name' : 'NAME',
    3.22 +              'mpoly' : 'MULTIPOLYGON',
    3.23 +              }
    3.24 +# http://www.census.gov/geo/cob/bdy/st/st00shp/st99_d00_shp.zip
    3.25 +st_shp = os.path.join(settings.GIS_DATA_DIR, 'census/state/st99_d00.shp')
    3.26 +
    3.27 +def run():
    3.28 +    # Creating and saving State models.
    3.29 +    lm = LayerMapping(State, st_shp, st_mapping,
    3.30 +                      unique=('name', 'fips'), encoding='cp437',
    3.31 +                      transform=False)
    3.32 +    lm.save(verbose=True)
    3.33 +
    3.34 +    # Creating and saving County models.
    3.35 +    lm = LayerMapping(County, co_shp, co_mapping,
    3.36 +                      unique=('name', 'state'), encoding='cp437',
    3.37 +                      transform=False)
    3.38 +    lm.save(verbose=True)
    3.39 +
    3.40 +    # Adding the Google Projection to the `spatial_ref_sys` table.
    3.41 +    add_postgis_srs(SpatialReference(900913))
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/census/models.py	Sun May 11 17:36:25 2008 -0700
     4.3 @@ -0,0 +1,21 @@
     4.4 +from django.contrib.gis.db import models
     4.5 +
     4.6 +class State(models.Model):
     4.7 +    fips = models.CharField(max_length=2)
     4.8 +    name = models.CharField(max_length=20)
     4.9 +    mpoly = models.MultiPolygonField(srid=4269)
    4.10 +    objects = models.GeoManager()
    4.11 +
    4.12 +    def __unicode__(self): return self.name
    4.13 +
    4.14 +class County(models.Model):
    4.15 +    state = models.ForeignKey(State)
    4.16 +    fips = models.CharField(max_length=3)
    4.17 +    name = models.CharField(max_length=90)
    4.18 +    mpoly = models.MultiPolygonField(srid=4269)
    4.19 +    objects = models.GeoManager()
    4.20 +
    4.21 +    class Meta:
    4.22 +        verbose_name_plural = 'Counties'
    4.23 +
    4.24 +    def __unicode__(self): return self.name
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/manage.py	Sun May 11 17:36:25 2008 -0700
     5.3 @@ -0,0 +1,11 @@
     5.4 +#!/usr/bin/env python
     5.5 +from django.core.management import execute_manager
     5.6 +try:
     5.7 +    import settings # Assumed to be in the same directory.
     5.8 +except ImportError:
     5.9 +    import sys
    5.10 +    sys.stderr.write("Error: Can't find the file 'settings.py' in the directory containing %r. It appears you've customized things.\nYou'll have to run django-admin.py, passing it your settings module.\n(If the file settings.py does indeed exist, it's causing an ImportError somehow.)\n" % __file__)
    5.11 +    sys.exit(1)
    5.12 +
    5.13 +if __name__ == "__main__":
    5.14 +    execute_manager(settings)
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/settings.py	Sun May 11 17:36:25 2008 -0700
     6.3 @@ -0,0 +1,88 @@
     6.4 +import os
     6.5 +
     6.6 +# Django settings for where project.
     6.7 +DEBUG = True
     6.8 +TEMPLATE_DEBUG = DEBUG
     6.9 +
    6.10 +ADMINS = (
    6.11 +    # ('Your Name', 'your_email@domain.com'),
    6.12 +)
    6.13 +
    6.14 +MANAGERS = ADMINS
    6.15 +
    6.16 +DATABASE_ENGINE = 'postgresql_psycopg2'           # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
    6.17 +DATABASE_NAME = 'where2'             # Or path to database file if using sqlite3.
    6.18 +DATABASE_USER = 'where2'             # Not used with sqlite3.
    6.19 +DATABASE_PASSWORD = ''         # Not used with sqlite3.
    6.20 +DATABASE_HOST = ''             # Set to empty string for localhost. Not used with sqlite3.
    6.21 +DATABASE_PORT = '5433'             # Set to empty string for default. Not used with sqlite3.
    6.22 +
    6.23 +GOOGLE_MAPS_API_KEY='ABQIAAAAMUTZALEj0zUjLExRimtu-hQ59Tu8jVbjhYsoxBJh_RvJrtxWSxTvrMoejJ9mh6jiwgOzqBkWByBdHA'
    6.24 +
    6.25 +GIS_DATA_DIR = os.path.join(os.path.dirname(__file__), 'data')
    6.26 +
    6.27 +# Local time zone for this installation. Choices can be found here:
    6.28 +# http://en.wikipedia.org/wiki/List_of_tz_zones_by_name
    6.29 +# although not all choices may be available on all operating systems.
    6.30 +# If running in a Windows environment this must be set to the same as your
    6.31 +# system time zone.
    6.32 +TIME_ZONE = 'America/Chicago'
    6.33 +
    6.34 +# Language code for this installation. All choices can be found here:
    6.35 +# http://www.i18nguy.com/unicode/language-identifiers.html
    6.36 +LANGUAGE_CODE = 'en-us'
    6.37 +
    6.38 +SITE_ID = 1
    6.39 +
    6.40 +# If you set this to False, Django will make some optimizations so as not
    6.41 +# to load the internationalization machinery.
    6.42 +USE_I18N = True
    6.43 +
    6.44 +# Absolute path to the directory that holds media.
    6.45 +# Example: "/home/media/media.lawrence.com/"
    6.46 +MEDIA_ROOT = ''
    6.47 +
    6.48 +# URL that handles the media served from MEDIA_ROOT. Make sure to use a
    6.49 +# trailing slash if there is a path component (optional in other cases).
    6.50 +# Examples: "http://media.lawrence.com", "http://example.com/media/"
    6.51 +MEDIA_URL = ''
    6.52 +
    6.53 +# URL prefix for admin media -- CSS, JavaScript and images. Make sure to use a
    6.54 +# trailing slash.
    6.55 +# Examples: "http://foo.com/media/", "/media/".
    6.56 +ADMIN_MEDIA_PREFIX = '/media/'
    6.57 +
    6.58 +# Make this unique, and don't share it with anybody.
    6.59 +SECRET_KEY = 'g#iu)v^=0f##w-xu5@=-x#np7fvamw5jdagr4!e0n7jach!q2a'
    6.60 +
    6.61 +# List of callables that know how to import templates from various sources.
    6.62 +TEMPLATE_LOADERS = (
    6.63 +    'django.template.loaders.filesystem.load_template_source',
    6.64 +    'django.template.loaders.app_directories.load_template_source',
    6.65 +#     'django.template.loaders.eggs.load_template_source',
    6.66 +)
    6.67 +
    6.68 +MIDDLEWARE_CLASSES = (
    6.69 +    'django.middleware.common.CommonMiddleware',
    6.70 +    'django.contrib.sessions.middleware.SessionMiddleware',
    6.71 +    'django.contrib.auth.middleware.AuthenticationMiddleware',
    6.72 +    'django.middleware.doc.XViewMiddleware',
    6.73 +)
    6.74 +
    6.75 +ROOT_URLCONF = 'where.urls'
    6.76 +
    6.77 +TEMPLATE_DIRS = (
    6.78 +    # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates".
    6.79 +    # Always use forward slashes, even on Windows.
    6.80 +    # Don't forget to use absolute paths, not relative paths.
    6.81 +)
    6.82 +
    6.83 +INSTALLED_APPS = (
    6.84 +    'django.contrib.auth',
    6.85 +    'django.contrib.contenttypes',
    6.86 +    'django.contrib.sessions',
    6.87 +    'django.contrib.sites',
    6.88 +    'where2.census',
    6.89 +    'where2.tabc',
    6.90 +    'where2.texas',
    6.91 +)
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/tabc/__init__.py	Sun May 11 17:36:25 2008 -0700
     7.3 @@ -0,0 +1,1 @@
     7.4 +from models import License, Location, Owner
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/tabc/load.py	Sun May 11 17:36:25 2008 -0700
     8.3 @@ -0,0 +1,150 @@
     8.4 +import csv, datetime, hashlib, os, re
     8.5 +from itertools import izip
     8.6 +
     8.7 +from django.conf import settings
     8.8 +from django.db import transaction
     8.9 +from django.contrib.gis.geos import *
    8.10 +
    8.11 +from models import Location, Owner, License
    8.12 +
    8.13 +mail_regex = re.compile(r'^(?P<number>\d+) (?P<street>.+)$')
    8.14 +license_regex = re.compile(r'^(?P<class>[A-Z ]{2})(?P<number>\d+)$')
    8.15 +
    8.16 +def get_csv_table():
    8.17 +    "Gets the CSV object for the TABC data file."
    8.18 +    data_file = os.path.join(settings.GIS_DATA_DIR, 'tabc/all.txt')
    8.19 +    return csv.reader(open(data_file))
    8.20 +
    8.21 +def loc_hash(loc, digest=True):
    8.22 +    "Creates a hash from the given Location object."
    8.23 +    hash = hashlib.sha1()
    8.24 +    atts = ['number', 'street', 'city', 'state', 'zipcode', 'foreign',
    8.25 +            'desc', 'desc2', 'point']
    8.26 +    for att in atts: hash.update(str(getattr(loc, att)))
    8.27 +    if digest:
    8.28 +        return hash.hexdigest()
    8.29 +    else:
    8.30 +        return hash
    8.31 +
    8.32 +def owner_hash(o):
    8.33 +    "Creates a hash from the given Owner object."
    8.34 +    hash = loc_hash(o.location, digest=False)
    8.35 +    hash.update(o.name)
    8.36 +    return hash.hexdigest()
    8.37 +    
    8.38 +def get_field_lens():
    8.39 +    """
    8.40 +    Gets the maximum length for each field in the TABC CSV file.
    8.41 +    """
    8.42 +    table = get_csv_table()
    8.43 +    header = table.next()
    8.44 +
    8.45 +    # Dictionary indexed by each column header.
    8.46 +    len_dict = dict((col, []) for col in header)
    8.47 +
    8.48 +    # Incrementing through each row in the CSV file.
    8.49 +    for row in table:
    8.50 +        # Incrementing over each column label in the header, and
    8.51 +        # appending the length of the value to the array for
    8.52 +        # the data column.
    8.53 +        for col, val in izip(header, row): len_dict[col].append(len(val))
    8.54 +
    8.55 +    # Getting the maximum length for each column item
    8.56 +    # and setting that value in the dictionary.
    8.57 +    for col, arr in len_dict.iteritems(): len_dict[col] = max(arr)
    8.58 +    return len_dict
    8.59 +
    8.60 +def get_date(s):
    8.61 +    """
    8.62 +    Returns a date object from a string with `YYYYMMDD` format, or
    8.63 +    None if the string is invalid.
    8.64 +    """
    8.65 +    try:
    8.66 +        return datetime.date(int(s[:4]), int(s[4:6]), int(s[6:]))
    8.67 +    except ValueError:
    8.68 +        return None
    8.69 +
    8.70 +def cache_or_save(cache, key, model):
    8.71 +    if key in cache:
    8.72 +        return cache[key]
    8.73 +    else:
    8.74 +        model.save()
    8.75 +        cache[key] = model
    8.76 +        return model
    8.77 +
    8.78 +@transaction.commit_on_success
    8.79 +def run():
    8.80 +    table = get_csv_table()
    8.81 +    
    8.82 +    # These dictionaries are for caches of the data.  Using dictionaries
    8.83 +    # keyed to objects is much quicker than using `get_or_create` because
    8.84 +    # it _significantly_ reduces the number of times the database is hit.
    8.85 +    location_cache = {}
    8.86 +    owner_cache = {}
    8.87 +
    8.88 +    header = table.next()
    8.89 +    for i, row in enumerate(table):
    8.90 +        # Unpacking every element in the CSV row into a variable.
    8.91 +        (cnty_name, lic_permit, exp, loc_num, loc_st, tn1, tn2, tn3, 
    8.92 +         owner_name1, owner_name2, loc_desc1, loc_desc2, loc_for, 
    8.93 +         loc_city, loc_state, loc_zip, mail_st, mail_desc, mail_for, 
    8.94 +         mail_city, mail_state, mail_zip, issue, phone) = row
    8.95 +
    8.96 +        # Creating & saving the permit location (strings are used  for
    8.97 +        # street number because some address numbers have non-numeric 
    8.98 +        # components). 
    8.99 +        if not loc_num: loc_num = ''
   8.100 +        location = Location(number=loc_num, street=loc_st, city=loc_city,
   8.101 +                            state=loc_state, zipcode=loc_zip[:5], zip4=loc_zip[5:],
   8.102 +                            foreign=loc_for, desc=loc_desc1, desc2=loc_desc2, 
   8.103 +                            point=Point(0, 0)) # Point(0, 0) so we don't have NULL geometry columns.
   8.104 +        location = cache_or_save(location_cache, loc_hash(location), location)
   8.105 +            
   8.106 +        # There's not an explicit field for the street number for the
   8.107 +        # mailing addresses -- attempting to extract here.
   8.108 +        m = mail_regex.match(mail_st)
   8.109 +        if m:
   8.110 +            mail_num = m.group('number')
   8.111 +            mail_st = m.group('street')
   8.112 +        else:
   8.113 +            mail_num = ''
   8.114 +
   8.115 +        # Creating and saving the mailing location.
   8.116 +        mail_location = Location(number=mail_num, street=mail_st, city=mail_city, 
   8.117 +                                 state=mail_state, zipcode=mail_zip[:5], zip4=mail_zip[5:],
   8.118 +                                 foreign=mail_for, desc='', desc2='', point=Point(0, 0))
   8.119 +        mail_location = cache_or_save(location_cache, loc_hash(mail_location), mail_location)
   8.120 +
   8.121 +        # Creating and saving the owner information.
   8.122 +        owner = Owner(location=mail_location, name=owner_name1)
   8.123 +        owner = cache_or_save(owner_cache, owner_hash(owner), owner)
   8.124 +                
   8.125 +        m = license_regex.match(lic_permit)
   8.126 +        lclass, num = m.group('class').strip(), int(m.group('number'))
   8.127 +        issued, expires = get_date(issue), get_date(exp)
   8.128 +        
   8.129 +        license = License(number=num, license_class=lclass, issued=issued, expires=expires,
   8.130 +                          location=location, owner=owner, phone=phone, 
   8.131 +                          tradename=unicode(tn1, 'cp437'), tradename2=unicode(tn2, 'cp437'))
   8.132 +        license.save()
   8.133 +        print license
   8.134 +
   8.135 +# qs = License.objects.filter(location__state='TX').select_related('location')
   8.136 +def gc(license_qs, gc_type='local'):
   8.137 +    from geocode import geocode
   8.138 +    gc_kwargs = {'order' : [gc_type], 'first' : True}
   8.139 +    if gc_type is 'gapi': gc_kwargs['wait'] = 0.4
   8.140 +    num_gc, total = 0, 0
   8.141 +    for l in license_qs:
   8.142 +        loc = l.location
   8.143 +        geo = geocode(loc.addr_str, **gc_kwargs)
   8.144 +        total += 1
   8.145 +        first = geo['first']
   8.146 +        if first: 
   8.147 +            lon, lat = geo[first][0]['lon'], geo[first][0]['lat']
   8.148 +            pnt = Point(lon, lat, srid=4326)
   8.149 +            loc.point = pnt
   8.150 +            loc.save()
   8.151 +            num_gc += 1
   8.152 +            if num_gc % 100 == 0: 
   8.153 +                print '%d (%d attempts)..' % (num_gc, total)
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/tabc/models.py	Sun May 11 17:36:25 2008 -0700
     9.3 @@ -0,0 +1,64 @@
     9.4 +from django.contrib.gis.db import models
     9.5 +
     9.6 +# Header from TABC CSV file.
     9.7 +# 'COUNTY NAME', 'CLASS LICENSE PERMIT', 'EXPIRATION DATE', 'LOCATION NUMBER', 'LOCATION STREET', 'TRADENAME', 'TRADENAME 2', 'TRADENAME 3', 'OWNER NAME', 'OWNER NAME 2', 'LOCATION DESCRIPTION', 'LOCATION DESCRIPTION 2', 'LOCATION FOREIGN', 'LOCATION CITY', 'LOCATION STATE', 'LOCATION ZIP', 'MAIL STREET', 'MAIL DESCRIPTION', 'MAIL FOREIGN', 'MAIL CITY', 'MAIL STATE', 'MAIL ZIP', 'ORIGINAL ISSUE DATE', 'PHONE NUMBER'
     9.8 +
     9.9 +class Location(models.Model):
    9.10 +    number = models.CharField(max_length=8)
    9.11 +    street = models.CharField(max_length=35)
    9.12 +    city = models.CharField(max_length=20)
    9.13 +    state = models.USStateField()
    9.14 +    zipcode = models.CharField(max_length=5)
    9.15 +    zip4 = models.CharField(max_length=4)
    9.16 +    foreign = models.CharField(max_length=20)
    9.17 +    desc = models.CharField(max_length=35)
    9.18 +    desc2 = models.CharField(max_length=21)
    9.19 +    # We are using a projected coordinate system for our PointField
    9.20 +    # to ease distance calculations.
    9.21 +    point = models.PointField(srid=900913)
    9.22 +    objects = models.GeoManager()
    9.23 +
    9.24 +    def __unicode__(self):
    9.25 +        atts = [getattr(self, att) for att in ['number', 'street', 'city', 'state', 'zipcode', 'foreign']]
    9.26 +        return ' '.join([str(a) for a in atts if a])
    9.27 +
    9.28 +    @property
    9.29 +    def addr_str(self):
    9.30 +        """
    9.31 +        Returns a properly formatted address string for use
    9.32 +        in Geocoding.
    9.33 +        """
    9.34 +        addr_parts = []
    9.35 +        if self.number:
    9.36 +            addr_parts.append('%s %s' % (self.number, self.street))
    9.37 +        else:
    9.38 +            addr_parts.append(self.street)
    9.39 +        if self.zip4:
    9.40 +            zip_str = '%s-%s' % (self.zipcode, self.zip4)
    9.41 +        else:
    9.42 +            zip_str = self.zipcode
    9.43 +        addr_parts.append(', %s, %s %s' % (self.city, self.state, zip_str))
    9.44 +        return ''.join(addr_parts)
    9.45 +
    9.46 +class Owner(models.Model):
    9.47 +    location = models.ForeignKey(Location)
    9.48 +    name = models.CharField(max_length=30)
    9.49 +    objects = models.GeoManager()
    9.50 +
    9.51 +    def __unicode__(self):
    9.52 +        return self.name
    9.53 +
    9.54 +class License(models.Model):
    9.55 +    number = models.IntegerField()
    9.56 +    license_class = models.CharField(max_length=2)
    9.57 +    issued = models.DateField(null=True)
    9.58 +    expires = models.DateField(null=True)
    9.59 +    location = models.ForeignKey(Location)
    9.60 +    owner = models.ForeignKey(Owner)
    9.61 +    phone = models.CharField(max_length=10)
    9.62 +    tradename = models.CharField(max_length=35)
    9.63 +    tradename2 = models.CharField(max_length=35)
    9.64 +    objects = models.GeoManager()
    9.65 +
    9.66 +    def __unicode__(self):
    9.67 +        return u'%s %s - %s' % (self.license_class, self.number, self.tradename)
    10.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    10.2 +++ b/tabc/rebuild.py	Sun May 11 17:36:25 2008 -0700
    10.3 @@ -0,0 +1,6 @@
    10.4 +from models import *
    10.5 +
    10.6 +def run():
    10.7 +    loc_cache = {}
    10.8 +    qs = Location.objects.values()
    10.9 +    
    11.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    11.2 +++ b/tabc/views.py	Sun May 11 17:36:25 2008 -0700
    11.3 @@ -0,0 +1,1 @@
    11.4 +# Create your views here.
    12.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    12.2 +++ b/texas/__init__.py	Sun May 11 17:36:25 2008 -0700
    12.3 @@ -0,0 +1,1 @@
    12.4 +from models import Neighborhood, Zip
    13.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    13.2 +++ b/texas/load.py	Sun May 11 17:36:25 2008 -0700
    13.3 @@ -0,0 +1,32 @@
    13.4 +import os
    13.5 +from django.conf import settings
    13.6 +from django.contrib.gis.utils import LayerMapping
    13.7 +from models import Neighborhood, Zip
    13.8 +
    13.9 +# Zillow neighborhood LayerMappng settings.
   13.10 +zillow_shp = os.path.join(settings.GIS_DATA_DIR, 'zillow/ZillowNeighborhoods-TX.shp')
   13.11 +zillow_mapping = {'name' : 'NAME',
   13.12 +                  'state' : 'STATE',
   13.13 +                  'county' : 'COUNTY',
   13.14 +                  'city' : 'CITY',
   13.15 +                  'region' : 'REGIONID',
   13.16 +                  'mpoly' : 'MULTIPOLYGON',
   13.17 +                  }
   13.18 +
   13.19 +# Zip code LayerMapping settings.
   13.20 +zip_mapping = {'code' : 'ZCTA',
   13.21 +               'mpoly' : 'MULTIPOLYGON',
   13.22 +               }
   13.23 +zip_shp = os.path.join(settings.GIS_DATA_DIR, 'census/zcta/zt48_d00.shp')
   13.24 +
   13.25 +def run():
   13.26 +    lm = LayerMapping(Neighborhood, zillow_shp, zillow_mapping, 
   13.27 +                      unique=('name', 'city'))
   13.28 +    lm.save(verbose=True)
   13.29 +
   13.30 +    # Creating and saving Zipcode models.  Because the `zcta`
   13.31 +    # shapefiles do not come with projection information, we
   13.32 +    # specify manually via the `source_srs` keyword.
   13.33 +    lm = LayerMapping(Zip, zip_shp, zip_mapping,
   13.34 +                      unique='code', source_srs=4269)
   13.35 +    lm.save(verbose=True)
    14.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    14.2 +++ b/texas/models.py	Sun May 11 17:36:25 2008 -0700
    14.3 @@ -0,0 +1,25 @@
    14.4 +from django.contrib.gis.db import models
    14.5 +
    14.6 +class Neighborhood(models.Model):
    14.7 +    "Model for Zillow Neighborhoods."
    14.8 +    name = models.CharField(max_length=64)
    14.9 +    state = models.CharField(max_length=2)
   14.10 +    city = models.CharField(max_length=64)
   14.11 +    county = models.CharField(max_length=43)
   14.12 +    region = models.IntegerField('Zillow Region Identifier')
   14.13 +    mpoly = models.MultiPolygonField(srid=3084)
   14.14 +    objects = models.GeoManager()
   14.15 +    
   14.16 +    def __unicode__(self):
   14.17 +        return '%s (%s)' % (self.name, self.city)
   14.18 +
   14.19 +class Zip(models.Model):
   14.20 +    code = models.CharField('Zip Code', max_length=5)
   14.21 +    mpoly = models.MultiPolygonField(srid=3084)
   14.22 +    objects = models.GeoManager()
   14.23 +
   14.24 +    class Meta:
   14.25 +        verbose_name_plural = 'Zip Codes'
   14.26 +
   14.27 +    def __unicode__(self): return self.code
   14.28 +
    15.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    15.2 +++ b/texas/views.py	Sun May 11 17:36:25 2008 -0700
    15.3 @@ -0,0 +1,1 @@
    15.4 +# Create your views here.
    16.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
    16.2 +++ b/urls.py	Sun May 11 17:36:25 2008 -0700
    16.3 @@ -0,0 +1,15 @@
    16.4 +from django.conf.urls.defaults import *
    16.5 +
    16.6 +# Uncomment this for admin:
    16.7 +#from django.contrib import admin
    16.8 +
    16.9 +urlpatterns = patterns('',
   16.10 +    # Example:
   16.11 +    # (r'^where/', include('where.foo.urls')),
   16.12 +
   16.13 +    # Uncomment this for admin docs:
   16.14 +    #(r'^admin/doc/', include('django.contrib.admindocs.urls')),
   16.15 +
   16.16 +    # Uncomment this for admin:
   16.17 +    #('^admin/(.*)', admin.site.root),
   16.18 +)