Initial commit of working zipdistance.

This commit is contained in:
Elf M. Sternberg 2010-10-13 09:05:17 -07:00
commit d645ccdd47
11 changed files with 243 additions and 0 deletions

12
.gitignore vendored Normal file
View File

@ -0,0 +1,12 @@
*.pyc
*.rej
*.orig
*.pyo
*#
.#*
.DS_Store
*~
indieflix/stages/chi/
indieflix/static/avatars/
*.xcf
common/ctctwspylib/.cache

1
AUTHORS Normal file
View File

@ -0,0 +1 @@
Elf M. Sternberg <elf.sternberg@gmail.com>

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
The MIT License
Copyright (c) 2008 Elf M. Sternberg and all contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE AND DATA IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

52
README Normal file
View File

@ -0,0 +1,52 @@
==============================
django-zipdistance
==============================
django-zipdistance is a simple application to find the distance
between any two zip codes. The fixture provided with this application
is derived from the Year 2000 Zip Code Tabulation Area (ZCTA) tables
provided by the US Census Bureau. The Census Bureau notes:
ZCTAs are generalized area representations of U.S. Postal Service
(USPS) ZIP Code service areas. In most instances the ZCTA code
equals the ZIP Code for an area. Some ZIP Codes represent very
few addresses (sometimes only one) and therefore will not appear
in the ZCTA database. ZCTA is a trademark of the U.S. Census
Bureau; ZIP Code is a registered trademark of the U.S. Postal
Service.
In short, the ZCTAs most likely, but are not guaranteed to, correspond
with ZIP Codes for any given address. In testing, this database
proved to be entirely acceptable for most of the United States. But
just to make sure, I repeat: THE SOFTWARE AND DATA FILES ARE PROVIDED
"AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS
OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
-----------------------------
Standard Usage:
Find all the zipcodes within 50 miles:
target = Zipmap.objects.get(zipcode = zip_form.cleaned_data['zipcode1'].strip())
zips = Zipmap.objects.distance_from(target, 50)
Find the distance between two zipcodes:
zip1 = Zipmap.objects.get(zipcode = zip_form.cleaned_data['zipcode1'].strip())
zip2 = Zipmap.objects.get(zipcode = zip_form.cleaned_data['zipcode1'].strip())
zip1.distance_between(zip_2)
Find all the stores within a given distance.
zips = Zipmap.objects.distance_from(target, 50)
stores = Store.objects.get(zipcode__in = [z.zipcode for z in zips])
That last one's not terribly efficient. If you used the ZipMap as a
way of storing zipcodes, you could probably come up with something
smarter.

1
requirements.txt Normal file
View File

@ -0,0 +1 @@
Django==1.2

26
setup.py Normal file
View File

@ -0,0 +1,26 @@
#!/usr/bin/env python
from setuptools import setup, find_packages
setup (
name='django-zipdistance',
version='0.1',
description='A zip code distance application for Django.',
author='Elf M. Sternberg',
author_email='elf.sternberg@gmail.com',
url='http://github.com/elfsternberg/django-zipdistance/',
license='MIT License',
classifiers=[
'Development Status :: 3 - Alpha',
'Environment :: Plugins',
'Framework :: Django',
'Intended Audience :: Developers',
'License :: OSI Approved :: BSD License',
'Programming Language :: Python',
'Topic :: Software Development :: Libraries :: Python Modules',
],
package_data = {
'': ['*.yaml.gz']
},
packages=find_packages(),
)

32
zipdistance/__init__.py Normal file
View File

@ -0,0 +1,32 @@
# Copyright 2010 by Elf M. Sternberg. All rights not expressly granted
# herein are reserved.
#
# Created in the United States of America.
#
# This digital media is protected by U.S. and international copyright
# and intellectual property laws. Unless otherwise specified, all
# information and screens appearing as part of this digital medium,
# including software, services, documents, text, images, icons, and
# logos design; the selection, assembly, arrangement, and design
# thereof; and the code that enables its presentation, are the sole
# property of Elf M. Sternberg.
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation files
# (the "Software"), to deal in the Software without restriction,
# including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software,
# and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE AND DATA IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
# KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
# WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

Binary file not shown.

74
zipdistance/models.py Normal file
View File

@ -0,0 +1,74 @@
from django.db import models
from django.db.models import Aggregate
from django.db.models.sql.aggregates import Aggregate as AggregateImpl
class DistanceFromImpl(AggregateImpl):
sql_function = ''
is_computed = True
is_ordinal = True
sql_template = ('3959 * acos( cos( radians(%(t_lat)f) ) * cos( radians( latitude ) ) * '
'cos( radians( longitude ) - radians(%(t_lon)f) ) + sin( radians(%(t_lat)f) ) * '
'sin( radians( latitude ) ) )')
def __init__(self, col, target, **extra):
self.col = col
self.target = target
self.extra = extra
def _default_alias(self):
return '%s__%s' % (str(self.target), self.__class__.__name__.lower())
default_alias = property(_default_alias)
def add_to_query(self, query, alias, col, source, is_summary):
super(DistanceFrom, self).__init__(col, source, is_summary, **self.extra)
query.aggregate_select[alias] = self
def as_sql(self, qn, connection):
"Return the aggregate, rendered as SQL."
return self.sql_template % { 't_lon': self.target.longitude,
't_lat': self.target.latitude }
class DistanceFrom(Aggregate):
name="DistanceFromImpl"
def add_to_query(self, query, alias, col, source, is_summary):
aggregate = DistanceFromImpl(col, source=source, is_summary=is_summary, **self.extra)
query.aggregates[alias] = aggregate
class ZipDistanceManager(models.Manager):
def distance_from(self, target, limit = 0):
qs = self.annotate(distance = DistanceFrom('zipcode', target = target))
if bool(limit):
qs = qs.filter(distance__lte = float(limit))
qs = qs.order_by('distance')
return qs
class ZipDistance(models.Model):
state = models.CharField(max_length = 2)
zipcode = models.CharField(max_length = 5, unique = True)
latitude = models.FloatField()
longitude = models.FloatField()
objects = ZipDistanceManager()
class Meta:
ordering = ['zipcode']
def __unicode__(self):
return '%s:%s' % (self.state, self.zipcode)
def distance_between(self, other):
return self.__class__.objects.distance_from(self).get(zipcode = other.zipcode).distance

23
zipdistance/tests.py Normal file
View File

@ -0,0 +1,23 @@
"""
This file demonstrates two different styles of tests (one doctest and one
unittest). These will both pass when you run "manage.py test".
Replace these with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.failUnlessEqual(1 + 1, 2)
__test__ = {"doctest": """
Another way to test that 1 + 1 is equal to 2.
>>> 1 + 1 == 2
True
"""}

1
zipdistance/views.py Normal file
View File

@ -0,0 +1 @@
# Create your views here.