Josh VanderLinden avatar Josh VanderLinden committed 0fce037

Fixed a 'maximum recursion' error that showed up for bad locations (when no
lat/lng could be determined). (GC #4)

Updated the ignores. Reformatted the README. Updated the management command.
Fixed some problems with casting nulls to floats in the views. Simplified the
setup script.

Comments (0)

Files changed (10)

 syntax: glob
 *.pyc
 *.swp
+dist
+build
+*.egg*
-include README LICENSE AUTHORS CHANGES reploc/templates/* reploc/media/*
-recursive-include reploc *.py *.js *.html *.gif
-recursive-include sample *
+include README README.rst LICENSE AUTHORS CHANGES
+recursive-include reploc *.*
+recursive-exclude reploc *.pyc .*.swp

README

-`django-reploc` is a project that allows you to install a Google Map on your site to display and filter "representatives" for your site. These representatives may be dealers/vendors for your products, your friends or business associates, or just places you've been and want to advertise. I built the application to be a dealer locator, but I realize the value in an application like this and tried to make it as generic as possible.
-
-==Features==
-
-  * Unlimited number of representatives.
-  * Unlimited number of locations _per_ representative.
-  * Automatic latitude/longitude determination for locations.  If there's a problem determining the coordinates to the address, you can enter them manually.
-  * Locations can have "attributes."  This is a way of specifying, for example, which locations carry which lines of your products.
-  * You can decide whether you want to use JavaScript or Python to do the heavy lifting.
-  * Users can search for locations within a radius of an address they specify.
-  * Offer your users driving directions to various representative locations.
-
-==Requirements==
-
-`django-reploc` requires at least Django 1.0.  For automatic coordinate determination, `django-reploc` requires the `geopy` library.  This can be installed using `easy_install geopy`.  The application also requires that you have a Google Maps API key.  To get one of those, simply go to [http://code.google.com/apis/maps/signup.html the Google Maps API page] and fill out the necessary information.  Finally, `django-reploc` relies heavily upon jQuery in order to operate.  I used the latest version of jQuery, which is currently 1.2.6.
-
-==Installation==
-
-Download `django-reploc` using *one* of the following methods:
-
-===easy_install===
-
-You can download the package from the [http://pypi.python.org/pypi/django-reploc/ CheeseShop] or use
-
-{{{
-easy_install django-reploc
-}}}
-
-to download and install `django-reploc`.
-
-===Package Download===
-
-Download the latest `.tar.gz` file from the downloads section and extract it somewhere you'll remember.  Use `python setup.py install` to install it.
-
-===Checkout from Subversion===
-
-Execute the following command (or use the equivalent function in a GUI such as TortoiseSVN), and make sure you're checking Pendulum out somewhere on the `PYTHONPATH`.
-
-{{{
-svn co http://django-reploc.googlecode.com/svn/trunk/reploc reploc
-}}}
-
-===Verifying Installation===
-
-The easiest way to ensure that you have successfully installed Pendulum is to execute a command such as:
-
-{{{
-python -c "import reploc; print reploc.get_version()"
-}}}
-
-If that displays the version of `django-reploc` that you tried to install, you're good to roll.  If you see something other than that, you probably need to check your `PYTHONPATH` environment variable.
-
-==Configuration==
-
-First of all, you must add this project to your list of `INSTALLED_APPS` in `settings.py`:
-
-{{{
-INSTALLED_APPS = (
-    'django.contrib.admin',
-    'django.contrib.auth',
-    'django.contrib.contenttypes',
-    'django.contrib.sessions',
-    'django.contrib.sites',
-    ...
-    'reploc',
-    ...
-)
-}}}
-
-Next you should add the context processor to your `TEMPLATE_CONTEXT_PROCESSORS` setting so the templates have access to the Google Maps API key.  You don't really need this step if you're going to put the API key straight into your template.
-
-{{{
-TEMPLATE_CONTEXT_PROCESSORS = (
-    'django.core.context_processors.auth',
-    'django.core.context_processors.i18n',
-    'django.core.context_processors.media',
-    'reploc.context_processors.representatives',
-)
-}}}
-
-Define your Google Maps API key in your `settings.py` file
-
-{{{
-GOOGLE_MAPS_KEY = 'sdfsafasfdasfdasdf'
-}}}
-
-Additionally, you may specify whether you would like the grunt work (distance calculations and whatnot) handled by JavaScript or Python:
-
-{{{
-REPLOC_USE_JS = False
-}}}
-
-This will probably never be used much, but it's there just in case.  The application defaults to using JavaScript.
-
-Run `manage.py syncdb`.  This creates a few tables in your database that are necessary for operation.
-
-Next, you should add an entry to your main `urls.py` file.  For example:
-
-{{{
-from django.conf.urls.defaults import *
-
-from django.contrib import admin
-admin.autodiscover()
-
-urlpatterns = patterns('',
-    (r'^admin/(.*)', admin.site.root),
-    (r'^locator/', include('reploc.urls')),
-)
-}}}
-
-Finally, you'll probably want to copy the media files that I use in `django-reploc`, unless you have some of your own.  Those files can be found in the `/media/` directory of the project.  There are really only two files that you should need to copy to your media directory: `reploc/media/js/jquery-1.3.1.min.js` and `reploc/media/img/ajax.gif` (see http://code.google.com/p/django-reploc/source/browse/#svn/trunk/reploc/media for the specific files).  Alternatively, you may just override the templates to use whatever you want.  I make no guarantees that the application will still work if you do that though ;)
-
-==Usage==
-
-As soon as you have all of the configuration taken care of, simply fire up your site (or restart it) and jump into the Django administration interface.  You can add locations straight from the "Add Representative" page if you'd like.  When you're done, head on over to http://www.yourwebsite.com/locator/ (or whatever it happens to be in your case) to see the application in action.
-
-===Updating Location Coordinates===
-
-I've created a utility to help you update the location coordinates if you feel the need.  They should be updated each time you save a location, but if you want to update all of the locations in one swing, you can use the command `./manage.py reploc_update_coords`.
+``django-reploc`` is a project that allows you to install a Google Map on your
+site to display and filter "representatives" for your site. These
+representatives may be dealers/vendors for your products, your friends or
+business associates, or just places you've been and want to advertise. I built
+the application to be a dealer locator, but I realize the value in an
+application like this and tried to make it as generic as possible.
+
+Features
+========
+
+* Unlimited number of representatives.
+* Unlimited number of locations _per_ representative.
+* Automatic latitude/longitude determination for locations.  If there's a
+  problem determining the coordinates to the address, you can enter them
+  manually.
+* Locations can have "attributes."  This is a way of specifying, for example,
+  which locations carry which lines of your products.
+* You can decide whether you want to use JavaScript or Python to do the heavy
+  lifting.
+* Users can search for locations within a radius of an address they specify.
+* Offer your users driving directions to various representative locations.
+
+Requirements
+============
+
+``django-reploc`` requires at least Django 1.0.  For automatic coordinate
+determination, ``django-reploc`` requires the ``geopy`` library.  This can be
+installed using ``easy_install geopy``.  The application also requires that you
+have a Google Maps API key.  To get one of those, simply go to `the Google Maps
+API page <http://code.google.com/apis/maps/signup.html>`_ and fill out the
+necessary information.  Finally, ``django-reploc`` relies heavily upon jQuery
+in order to operate.  I used the latest version of jQuery, which is currently
+1.2.6.
+
+Installation
+============
+
+Download ``django-reploc`` using *one* of the following methods:
+
+easy_install
+------------
+
+You can download the package from the `CheeseShop
+<http://pypi.python.org/pypi/django-reploc/>`_ or use::
+
+    easy_install django-reploc
+
+to download and install ``django-reploc``.
+
+pip
+---
+
+Install ``django-reploc`` using::
+
+    pip install -U django-reploc
+
+Package Download
+----------------
+
+Download the latest ``.tar.gz`` file from the downloads section and extract it
+somewhere you'll remember.  Use ``python setup.py install`` to install it.
+
+Clone From Source Control
+-------------------------
+
+You can get the latest copy of the source code from any of the these official
+repositories::
+
+    hg clone http://bitbucket.org/codekoala/django-reploc
+    hg clone http://django-reploc.googlecode.com/hg django-reploc
+    git clone http://github.com/codekoala/django-reploc.git
+
+Verifying Installation
+----------------------
+
+The easiest way to ensure that you have successfully installed Pendulum is to
+execute a command such as::
+
+    python -c "import reploc; print reploc.get_version()"
+
+If that displays the version of ``django-reploc`` that you tried to install,
+you're good to roll.  If you see something other than that, you probably need
+to check your ``PYTHONPATH`` environment variable.
+
+Configuration
+=============
+
+First of all, you must add this project to your list of ``INSTALLED_APPS`` in
+``settings.py``::
+
+    INSTALLED_APPS = (
+        'django.contrib.admin',
+        'django.contrib.auth',
+        'django.contrib.contenttypes',
+        'django.contrib.sessions',
+        'django.contrib.sites',
+        ...
+        'reploc',
+        ...
+    )
+
+Next you should add the context processor to your
+``TEMPLATE_CONTEXT_PROCESSORS`` setting so the templates have access to the
+Google Maps API key.  You don't really need this step if you're going to put
+the API key straight into your template.
+
+::
+
+    TEMPLATE_CONTEXT_PROCESSORS = (
+        'django.core.context_processors.auth',
+        'django.core.context_processors.i18n',
+        'django.core.context_processors.media',
+        'reploc.context_processors.representatives',
+    )
+
+Define your Google Maps API key in your ``settings.py`` file::
+
+    GOOGLE_MAPS_KEY = 'sdfsafasfdasfdasdf'
+
+Additionally, you may specify whether you would like the grunt work (distance
+calculations and whatnot) handled by JavaScript or Python::
+
+    REPLOC_USE_JS = False
+
+This will probably never be used much, but it's there just in case.  The
+application defaults to using JavaScript.
+
+Run ``python manage.py syncdb``.  This creates a few tables in your database
+that are necessary for operation.
+
+Next, you should add an entry to your main ``urls.py`` file.  For example::
+
+    from django.conf.urls.defaults import *
+
+    from django.contrib import admin
+    admin.autodiscover()
+
+    urlpatterns = patterns('',
+        (r'^admin/(.*)', admin.site.root),
+        (r'^locator/', include('reploc.urls')),
+    )
+
+Finally, you'll probably want to copy the media files that I use in
+``django-reploc``, unless you have some of your own.  Those files can be found
+in the ``/media/`` directory of the project.  There are really only two files
+that you should need to copy to your media directory:
+``reploc/media/js/jquery-1.3.1.min.js`` and ``reploc/media/img/ajax.gif`` (see
+http://code.google.com/p/django-reploc/source/browse/#hg%2Freploc%2Fmedia
+for the specific files).  Alternatively, you may just override the templates to
+use whatever you want.  I make no guarantees that the application will still
+work if you do that though ;)
+
+Usage
+=====
+
+As soon as you have all of the configuration taken care of, simply fire up your
+site (or restart it) and jump into the Django administration interface.  You
+can add locations straight from the "Add Representative" page if you'd like.
+When you're done, head on over to http://www.yourwebsite.com/locator/ (or
+whatever it happens to be in your case) to see the application in action.
+
+Updating Location Coordinates
+-----------------------------
+
+I've created a utility to help you update the location coordinates if you feel
+the need.  They should be updated each time you save a location, but if you
+want to update all of the locations in one swing, you can use the command
+``python manage.py reploc_update_coords``.

reploc/__init__.py

-import os
-
-VERSION = (0, 1, 0, 'pre3')
+VERSION = (0, 1, 1, 'pre1')
 
 def version():
     return '%s.%s.%s-%s' % VERSION

reploc/management/commands/reploc_update_coords.py

+import traceback
+
 from django.core.management.base import BaseCommand
 from reploc.models import Location
 from reploc import utils
     def handle(self, **options):
         self.validate(display_num_errors=False)
 
-        print 'Updating location coordinates...'
+        self.stdout.write('Updating location coordinates...\n')
 
         count = {'s': 0, 'f': 0}
 
         for l in Location.objects.active():
             try:
                 coords = utils.get_coordinates(l)
-                print '\t%s' % l.string_address,
+                self.stdout.write('\t%s\t' % l.string_address)
             except:
-                print 'Error'
+                self.stdout.write('Error getting coordinates for %s:\n%s\n\n' % (l, traceback.format_exc()))
                 l.coordinate_error = True
                 l.save()
                 count['f'] += 1
             else:
-                print coords
+                self.stdout.write('%s\n' % (coords,))
                 l.update_coordinates(coords)
                 count['s'] += 1
 
-        print 'Successful updates: %i' % count['s']
-        print 'Failed updates: %i' % count['f']
-        print 'All done!'
+        self.stdout.write('Successful updates: %i\n' % count['s'])
+        self.stdout.write('Failed updates: %i\n' % count['f'])
+        self.stdout.write('All done!\n')
 
 class RepresentativeManager(models.Manager):
     def active(self):
-        return self.get_query_set().filter(is_active=True)
+        return self.filter(is_active=True)
 
 class Representative(models.Model):
     """
 
 class LocationManager(models.Manager):
     def active(self):
-        return self.get_query_set().filter(representative__is_active=True)
+        return self.filter(representative__is_active=True)
 
 class Location(models.Model):
     """
 from django.db.models.signals import post_save
 from django.conf import settings
 from reploc.models import Location
-from decimal import Decimal
 from datetime import datetime, timedelta
 from geopy import geocoders
 
 
     now = datetime.now()
 
+    # bail out if there has been an error getting the coordinates; avoids
+    # infinite recursion
+    if instance.coordinate_error:
+        return
+
     # if the last check was within the last 5 minutes, skip the coord update
     # since we call the instance.save() method in this function, we would be
     # put in an infinite loop without something like this.
+from math import *
+
 from django.shortcuts import render_to_response
 from django.http import Http404
-from django.utils.simplejson.encoder import JSONEncoder
-from django.conf import settings
-from reploc.models import Representative, Location, Attribute
+from django.utils.simplejson import JSONEncoder
+from reploc.models import Location
 from reploc import utils
-from geopy import geocoders
-from math import *
 
 def get_locations(request):
     """
     the latitude and longitude fields because they are Decimal objects, and
     the JSONEncoder does not like them.
     """
+
+    lat = l.latitude
+    if lat:
+        lat = float(lat)
+
+    lng = l.longitude
+    if lng:
+        lng = float(lng)
+
     return {
             'representative': l.representative.name,
             'street1': l.street1,
             'fax': l.fax,
             'website': l.website,
             'email': l.email,
-            'lat': float(l.latitude),
-            'lng': float(l.longitude)
+            'lat': lat,
+            'lng': lng
         }
 #!/usr/bin/env python
 # -*- coding: utf-8 -*-
 
-from distutils.core import setup
+from setuptools import setup, find_packages
 import reploc
-import sys, os
-
-def fullsplit(path, result=None):
-    """
-    Split a pathname into components (the opposite of os.path.join) in a
-    platform-neutral way.
-    """
-    if result is None:
-        result = []
-    head, tail = os.path.split(path)
-    if head == '':
-        return [tail] + result
-    if head == path:
-        return result
-    return fullsplit(head, [tail] + result)
-
-packages, data_files = [], []
-root_dir = os.path.dirname(__file__)
-if root_dir != '':
-    os.chdir(root_dir)
-reploc_dir = 'reploc'
-
-for path, dirs, files in os.walk(reploc_dir):
-    # ignore hidden directories and files
-    for i, d in enumerate(dirs):
-        if d.startswith('.'): del dirs[i]
-
-    if '__init__.py' in files:
-        packages.append('.'.join(fullsplit(path)))
-    elif files:
-        data_files.append((path, [os.path.join(path, f) for f in files]))
 
 setup(
     name='django-reploc',
     version=reploc.version(),
-    url='http://code.google.com/p/django-reploc/',
+    description="A simple way for people to find representative locations on your Django-powered Web site.",
+    long_description=open('README.rst', 'r').read(),
+    keywords='django, dealers, vendors, representatives, locator, map',
     author='Josh VanderLinden',
-    author_email='codekoala@gmail.com',
+    author_email='codekoala at gmail dot com',
+    url='http://bitbucket.org/codekoala/django-reploc/',
     license='MIT',
-    packages=packages,
-    data_files=data_files,
-    description="A simple way for people to find representative locations on your Django-powered Web site.",
-    long_description="""
-django-reploc is a project that allows you to install a Google Map on your site to display and filter "representatives" for your site. These representatives may be dealers/vendors for your products, your friends or business associates, or just places you've been and want to advertise. I built the application to be a dealer locator, but I realize the value in an application like this and tried to make it as generic as possible.
-""",
-    keywords='django, dealers, vendors, representatives, locator, map',
+    package_dir={'reploc': 'reploc'},
+    include_package_data=True,
+    packages=find_packages(),
     classifiers=[
         'Development Status :: 4 - Beta',
         'Environment :: Web Environment',
         'Programming Language :: Python',
         'Topic :: Communications',
         'Topic :: Internet :: WWW/HTTP :: Dynamic Content'
-    ]
+    ],
+    zip_safe=False
 )
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.