Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add point support

  • Loading branch information...
commit bff87a061d732df1f28952e068c60381a6782beb 1 parent 6ae2a65
@jsatt jsatt authored
View
17 boundaryservice/admin.py
@@ -2,7 +2,8 @@
from django.contrib.gis.admin import OSMGeoAdmin
from tastypie.models import ApiAccess, ApiKey
-from boundaryservice.models import BoundarySet, Boundary, Shapefile
+from boundaryservice.models import (BoundarySet, Boundary, PointSet, Point,
+ Shapefile)
class ApiAccessAdmin(admin.ModelAdmin):
@@ -31,6 +32,20 @@ class BoundaryAdmin(OSMGeoAdmin):
admin.site.register(Boundary, BoundaryAdmin)
+class PointSetAdmin(admin.ModelAdmin):
+ list_filter = ('authority', 'domain')
+
+admin.site.register(PointSet, PointSetAdmin)
+
+
+class PointAdmin(OSMGeoAdmin):
+ list_display = ('kind', 'name', 'external_id')
+ list_display_links = ('name', 'external_id')
+ list_filter = ('kind',)
+
+admin.site.register(Point, PointAdmin)
+
+
class ShapefileAdmin(admin.ModelAdmin):
list_display = ('name', 'authority', 'domain')
list_display_links = ('name',)
View
176 boundaryservice/management/commands/loadshapefiles.py
@@ -14,11 +14,11 @@
from django.core.management.base import BaseCommand
from django.db import connections, DEFAULT_DB_ALIAS, transaction
-from boundaryservice.models import BoundarySet, Boundary, NAMERS, Shapefile
+from boundaryservice.models import (BoundarySet, Boundary, NAMERS, PointSet,
+ Point, Shapefile)
settings.DEFAULT_SHAPEFILES_DIR = getattr(settings, 'SHAPEFILES_DIR',
'media/shapefiles')
-GEOMETRY_COLUMN = 'shape'
class Command(BaseCommand):
@@ -48,11 +48,12 @@ def handle(self, *args, **options):
sys.path.append(options['data_dir'])
try:
from definitions import SHAPEFILES
+ shapefiles = SHAPEFILES
except ImportError:
- SHAPEFILES = {}
+ shapefiles = {}
for sf in Shapefile.objects.all():
- SHAPEFILES[sf.name] = {
+ shapefiles[sf.name] = {
'file': sf.file.name.replace(
'%s/' % settings.SHAPEFILES_SUBDIR, '', 1),
'singular': sf.singular,
@@ -75,17 +76,17 @@ def handle(self, *args, **options):
only = options['only'].upper().split(',')
# TODO: stripping whitespace here because optparse doesn't handle
# it correctly
- sources = [s for s in SHAPEFILES
+ sources = [s for s in shapefiles
if s.replace(' ', '').upper() in only]
elif options['except']:
exceptions = options['except'].upper().split(',')
# See above
- sources = [s for s in SHAPEFILES
+ sources = [s for s in shapefiles
if s.replace(' ', '').upper() not in exceptions]
else:
- sources = [s for s in SHAPEFILES]
+ sources = [s for s in shapefiles]
- for kind, config in SHAPEFILES.items():
+ for kind, config in shapefiles.items():
if kind not in sources:
log.info('Skipping %s.' % kind)
continue
@@ -99,38 +100,65 @@ def load_set(self, kind, config, options):
log.info('Processing %s.' % kind)
if options['clear']:
- bset = None
+ dset = None
try:
- bset = BoundarySet.objects.get(name=kind)
+ dset = BoundarySet.objects.get(name=kind)
- if bset:
+ if dset:
log.info('Clearing old %s.' % kind)
- bset.boundaries.all().delete()
- bset.delete()
+ dset.boundaries.all().delete()
+ dset.delete()
log.info('Loading new %s.' % kind)
except BoundarySet.DoesNotExist:
log.info('No existing boundary set of kind [%s] so nothing to '
'delete' % kind)
+ try:
+ dset = PointSet.objects.get(name=kind)
+
+ if dset:
+ log.info('Clearing old %s.' % kind)
+ dset.points.all().delete()
+ dset.delete()
+
+ log.info('Loading new %s.' % kind)
+ except PointSet.DoesNotExist:
+ log.info('No existing point set of kind [%s] so nothing to '
+ 'delete' % kind)
+
path = os.path.join(options['data_dir'], config['file'])
datasources = create_datasources(path)
layer = datasources[0][0]
-
- # Create BoundarySet
- bset = BoundarySet.objects.create(
- name=kind,
- singular=config['singular'],
- kind_first=config['kind_first'],
- authority=config['authority'],
- domain=config['domain'],
- last_updated=config['last_updated'],
- href=config['href'],
- notes=config['notes'],
- count=len(layer),
- metadata_fields=layer.fields)
+ data_type = layer.geom_type.name
+
+ # create dataset
+ if data_type in ['Polygon', 'MultiPolygon']:
+ dset = BoundarySet.objects.create(
+ name=kind,
+ singular=config['singular'],
+ kind_first=config['kind_first'],
+ authority=config['authority'],
+ domain=config['domain'],
+ last_updated=config['last_updated'],
+ href=config['href'],
+ notes=config['notes'],
+ count=len(layer),
+ metadata_fields=layer.fields)
+ elif data_type in ['Point', 'MultiPoint']:
+ dset = PointSet.objects.create(
+ name=kind,
+ singular=config['singular'],
+ kind_first=config['kind_first'],
+ authority=config['authority'],
+ domain=config['domain'],
+ last_updated=config['last_updated'],
+ href=config['href'],
+ notes=config['notes'],
+ count=len(layer),
+ metadata_fields=layer.fields)
for datasource in datasources:
log.info("Loading %s from %s" % (kind, datasource.name))
@@ -139,12 +167,20 @@ def load_set(self, kind, config, options):
log.warn('%s shapefile [%s] has multiple layers, using first.'
% (datasource.name, kind))
layer = datasource[0]
- self.add_boundaries_for_layer(config, layer, bset,
+
+ if data_type in ['Polygon', 'MultiPolygon']:
+ self.add_boundaries_for_layer(config, layer, dset,
+ options['database'])
+ elif data_type in ['Point', 'MultiPoint']:
+ self.add_points_for_layer(config, layer, dset,
options['database'])
# sync this with reality
- bset.count = Boundary.objects.filter(set=bset).count()
- bset.save()
- log.info('%s count: %i' % (kind, bset.count))
+ if data_type in ['Polygon', 'MultiPolygon']:
+ dset.count = Boundary.objects.filter(set=dset).count()
+ elif data_type in ['Point', 'MultiPoint']:
+ dset.count = Point.objects.filter(set=dset).count()
+ dset.save()
+ log.info('%s count: %i' % (kind, dset.count))
def polygon_to_multipolygon(self, geom):
"""
@@ -160,9 +196,9 @@ def polygon_to_multipolygon(self, geom):
else:
raise ValueError('Geom is neither Polygon nor MultiPolygon.')
- def add_boundaries_for_layer(self, config, layer, bset, database):
+ def add_boundaries_for_layer(self, config, layer, dset, database):
# Get spatial reference system for the postgis geometry field
- geometry_field = Boundary._meta.get_field_by_name(GEOMETRY_COLUMN)[0]
+ geometry_field = Boundary._meta.get_field_by_name('shape')[0]
SpatialRefSys = connections[database].ops.spatial_ref_sys()
db_srs = SpatialRefSys.objects.using(database).get(
srid=geometry_field.srid).srs
@@ -227,7 +263,7 @@ def add_boundaries_for_layer(self, config, layer, bset, database):
display_name = '%s %s' % (feature_name, config['singular'])
Boundary.objects.create(
- set=bset,
+ set=dset,
kind=config['singular'],
external_id=external_id,
name=feature_name,
@@ -237,6 +273,80 @@ def add_boundaries_for_layer(self, config, layer, bset, database):
simple_shape=simple_geometry.wkt,
centroid=geometry.geos.centroid)
+ def point_to_multipoint(self, geom):
+ """
+ Convert points to multipoints so all features are homogenous in the
+ database.
+ """
+ if geom.__class__.__name__ == 'Point':
+ g = OGRGeometry(OGRGeomType('MultiPoint'))
+ g.add(geom)
+ return g
+ elif geom.__class__.__name__ == 'MultiPoint':
+ return geom
+ else:
+ raise ValueError('Geom is neither Point nor MultiPoint.')
+
+ def add_points_for_layer(self, config, layer, dset, database):
+ # Get spatial reference system for the postgis geometry field
+ geometry_field = Point._meta.get_field_by_name('point')[0]
+ SpatialRefSys = connections[database].ops.spatial_ref_sys()
+ db_srs = SpatialRefSys.objects.using(database).get(
+ srid=geometry_field.srid).srs
+
+ if 'srid' in config and config['srid']:
+ layer_srs = SpatialRefSys.objects.get(srid=config['srid']).srs
+ else:
+ layer_srs = layer.srs
+
+ # Create a convertor to turn the source data into
+ transformer = CoordTransform(layer_srs, db_srs)
+
+ for feature in layer:
+ # Transform the geometry to the correct SRS
+ geometry = self.point_to_multipoint(feature.geom)
+ geometry.transform(transformer)
+
+ # Extract metadata into a dictionary
+ metadata = {}
+
+ for field in layer.fields:
+
+ # Decode string fields using encoding specified in definitions
+ # config
+ if config['encoding'] != '':
+ try:
+ metadata[field] = feature.get(field).decode(
+ config['encoding'])
+ # Only strings will be decoded, get value in normal way if
+ # int etc.
+ except AttributeError:
+ metadata[field] = feature.get(field)
+ else:
+ metadata[field] = feature.get(field)
+
+ external_id = config['ider'](feature)
+ feature_name = config['namer'](feature)
+
+ # If encoding is specified, decode id and feature name
+ if config['encoding'] != '':
+ external_id = external_id.decode(config['encoding'])
+ feature_name = feature_name.decode(config['encoding'])
+
+ if config['kind_first']:
+ display_name = '%s %s' % (config['singular'], feature_name)
+ else:
+ display_name = '%s %s' % (feature_name, config['singular'])
+
+ Point.objects.create(
+ set=dset,
+ kind=config['singular'],
+ external_id=external_id,
+ name=feature_name,
+ display_name=display_name,
+ metadata=metadata,
+ point=geometry.wkt)
+
def create_datasources(path):
if path.endswith('.zip'):
View
128 boundaryservice/migrations/0002_auto__add_point__add_pointset.py
@@ -0,0 +1,128 @@
+# -*- coding: utf-8 -*-
+import datetime
+from south.db import db
+from south.v2 import SchemaMigration
+from django.db import models
+
+
+class Migration(SchemaMigration):
+
+ def forwards(self, orm):
+ # Adding model 'Point'
+ db.create_table('boundaryservice_point', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=256)),
+ ('set', self.gf('django.db.models.fields.related.ForeignKey')(related_name='points', to=orm['boundaryservice.PointSet'])),
+ ('kind', self.gf('django.db.models.fields.CharField')(max_length=64)),
+ ('external_id', self.gf('django.db.models.fields.CharField')(max_length=64)),
+ ('name', self.gf('django.db.models.fields.CharField')(max_length=192, db_index=True)),
+ ('display_name', self.gf('django.db.models.fields.CharField')(max_length=256)),
+ ('metadata', self.gf('boundaryservice.fields.JSONField')(blank=True)),
+ ('point', self.gf('django.contrib.gis.db.models.fields.MultiPointField')(srid=4269, null=True)),
+ ))
+ db.send_create_signal('boundaryservice', ['Point'])
+
+ # Adding model 'PointSet'
+ db.create_table('boundaryservice_pointset', (
+ ('id', self.gf('django.db.models.fields.AutoField')(primary_key=True)),
+ ('slug', self.gf('django.db.models.fields.SlugField')(max_length=256)),
+ ('name', self.gf('django.db.models.fields.CharField')(unique=True, max_length=64)),
+ ('singular', self.gf('django.db.models.fields.CharField')(max_length=64)),
+ ('kind_first', self.gf('django.db.models.fields.BooleanField')(default=False)),
+ ('authority', self.gf('django.db.models.fields.CharField')(max_length=256)),
+ ('domain', self.gf('django.db.models.fields.CharField')(max_length=256)),
+ ('last_updated', self.gf('django.db.models.fields.DateField')()),
+ ('href', self.gf('django.db.models.fields.URLField')(max_length=200, blank=True)),
+ ('notes', self.gf('django.db.models.fields.TextField')(blank=True)),
+ ('count', self.gf('django.db.models.fields.IntegerField')()),
+ ('metadata_fields', self.gf('boundaryservice.fields.ListField')(separator='|', blank=True)),
+ ))
+ db.send_create_signal('boundaryservice', ['PointSet'])
+
+ def backwards(self, orm):
+ # Deleting model 'Point'
+ db.delete_table('boundaryservice_point')
+
+ # Deleting model 'PointSet'
+ db.delete_table('boundaryservice_pointset')
+
+ models = {
+ 'boundaryservice.boundary': {
+ 'Meta': {'ordering': "('kind', 'display_name')", 'object_name': 'Boundary'},
+ 'centroid': ('django.contrib.gis.db.models.fields.PointField', [], {'srid': '4269', 'null': 'True'}),
+ 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+ 'external_id': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'kind': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'metadata': ('boundaryservice.fields.JSONField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '192', 'db_index': 'True'}),
+ 'set': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'boundaries'", 'to': "orm['boundaryservice.BoundarySet']"}),
+ 'shape': ('django.contrib.gis.db.models.fields.MultiPolygonField', [], {'srid': '4269'}),
+ 'simple_shape': ('django.contrib.gis.db.models.fields.MultiPolygonField', [], {'srid': '4269'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '256'})
+ },
+ 'boundaryservice.boundaryset': {
+ 'Meta': {'ordering': "('name',)", 'object_name': 'BoundarySet'},
+ 'authority': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+ 'count': ('django.db.models.fields.IntegerField', [], {}),
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+ 'href': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'kind_first': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_updated': ('django.db.models.fields.DateField', [], {}),
+ 'metadata_fields': ('boundaryservice.fields.ListField', [], {'separator': "'|'", 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}),
+ 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'singular': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '256'})
+ },
+ 'boundaryservice.point': {
+ 'Meta': {'ordering': "('kind', 'display_name')", 'object_name': 'Point'},
+ 'display_name': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+ 'external_id': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'kind': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'metadata': ('boundaryservice.fields.JSONField', [], {'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '192', 'db_index': 'True'}),
+ 'point': ('django.contrib.gis.db.models.fields.MultiPointField', [], {'srid': '4269', 'null': 'True'}),
+ 'set': ('django.db.models.fields.related.ForeignKey', [], {'related_name': "'points'", 'to': "orm['boundaryservice.PointSet']"}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '256'})
+ },
+ 'boundaryservice.pointset': {
+ 'Meta': {'ordering': "('name',)", 'object_name': 'PointSet'},
+ 'authority': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+ 'count': ('django.db.models.fields.IntegerField', [], {}),
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '256'}),
+ 'href': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'kind_first': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_updated': ('django.db.models.fields.DateField', [], {}),
+ 'metadata_fields': ('boundaryservice.fields.ListField', [], {'separator': "'|'", 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '64'}),
+ 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'singular': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
+ 'slug': ('django.db.models.fields.SlugField', [], {'max_length': '256'})
+ },
+ 'boundaryservice.shapefile': {
+ 'Meta': {'object_name': 'Shapefile'},
+ 'authority': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}),
+ 'domain': ('django.db.models.fields.CharField', [], {'max_length': '250', 'blank': 'True'}),
+ 'encoding': ('django.db.models.fields.CharField', [], {'max_length': '50', 'blank': 'True'}),
+ 'file': ('django.db.models.fields.files.FileField', [], {'max_length': '100'}),
+ 'href': ('django.db.models.fields.URLField', [], {'max_length': '200', 'blank': 'True'}),
+ 'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
+ 'ider_fields': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
+ 'ider_namer': ('django.db.models.fields.CharField', [], {'default': "'simple'", 'max_length': '10'}),
+ 'kind_first': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
+ 'last_updated': ('django.db.models.fields.DateField', [], {'null': 'True', 'blank': 'True'}),
+ 'name': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
+ 'name_fields': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
+ 'name_namer': ('django.db.models.fields.CharField', [], {'default': "'simple'", 'max_length': '10'}),
+ 'notes': ('django.db.models.fields.TextField', [], {'blank': 'True'}),
+ 'simplification': ('django.db.models.fields.DecimalField', [], {'default': '0.0001', 'null': 'True', 'max_digits': '10', 'decimal_places': '8', 'blank': 'True'}),
+ 'singular': ('django.db.models.fields.CharField', [], {'max_length': '250'}),
+ 'srid': ('django.db.models.fields.IntegerField', [], {'null': 'True', 'blank': 'True'})
+ }
+ }
+
+ complete_apps = ['boundaryservice']
View
91 boundaryservice/models.py
@@ -169,6 +169,97 @@ def __unicode__(self):
return unicode(self.display_name)
+class PointSet(SluggedModel):
+ """
+ A set of related points, such as all bus stops or polling places.
+ """
+ name = models.CharField(max_length=64, unique=True,
+ help_text='Category of points, e.g. "Bus Stops".')
+ singular = models.CharField(max_length=64,
+ help_text='Name of a single point, e.g. "Bus Stop".')
+ kind_first = models.BooleanField(
+ help_text='If true, point display names will be "kind name" (e.g. Bus '
+ 'Stop 43), otherwise "name kind" (e.g. 43rd Precinct Polling Place).')
+ authority = models.CharField(
+ max_length=256,
+ help_text='The entity responsible for this data\'s accuracy, e.g. '
+ '"City of Chicago".')
+ domain = models.CharField(
+ max_length=256,
+ help_text='The area that this PointSet covers, e.g. "Chicago" or '
+ '"Illinois".')
+ last_updated = models.DateField(
+ help_text='The last time this data was updated from its authority (but'
+ ' not necessarily the date it is current as of).')
+ href = models.URLField(blank=True,
+ help_text='The url this data was found at, if any.')
+ notes = models.TextField(
+ blank=True,
+ help_text='Notes about loading this data, including any '
+ 'transformations that were applied to it.')
+ count = models.IntegerField(
+ help_text='Total number of features in this point set.')
+ metadata_fields = ListField(
+ separator='|', blank=True,
+ help_text='What, if any, metadata fields were loaded from the original'
+ ' dataset.')
+
+ class Meta:
+ ordering = ('name',)
+
+ def __unicode__(self):
+ """
+ Print plural names.
+ """
+ return unicode(self.name)
+
+
+class Point(SluggedModel):
+ """
+ A point object, such as a bus stop or polling place.
+ """
+ set = models.ForeignKey(
+ PointSet, related_name='points',
+ help_text='Category of points that this point belongs, e.g. '
+ '"Bus Stops".')
+ kind = models.CharField(
+ max_length=64,
+ help_text='A copy of PointSet\'s "singular" value for purposes of '
+ 'slugging and inspection.')
+ external_id = models.CharField(
+ max_length=64,
+ help_text='The points\' unique id in the source dataset, or a '
+ 'generated one.')
+ name = models.CharField(
+ max_length=192, db_index=True,
+ help_text='The name of this point, e.g. "Community Center".')
+ display_name = models.CharField(
+ max_length=256,
+ help_text='The name and kind of the field to be used for display '
+ 'purposes.')
+ metadata = JSONField(
+ blank=True,
+ help_text='The complete contents of the attribute table for this '
+ 'point from the source shapefile, structured as json.')
+ point = models.MultiPointField(
+ srid=4269,
+ null=True,
+ help_text='The point in EPSG:4269 projection.')
+
+ objects = models.GeoManager()
+
+ class Meta:
+ ordering = ('kind', 'display_name')
+ verbose_name_plural = 'Points'
+
+ def __unicode__(self):
+ """
+ Print names are formatted like "Bus Stop 42"
+ and will slug like "bus-stop-42".
+ """
+ return unicode(self.display_name)
+
+
class Shapefile(models.Model):
file = models.FileField(upload_to=settings.SHAPEFILES_SUBDIR)
name = models.CharField(
View
68 boundaryservice/resources.py
@@ -5,7 +5,7 @@
from tastypie.serializers import Serializer
from boundaryservice.authentication import NoOpApiKeyAuthentication
-from boundaryservice.models import BoundarySet, Boundary
+from boundaryservice.models import BoundarySet, Boundary, PointSet, Point
from boundaryservice.tastyhacks import SluggedResource
@@ -109,3 +109,69 @@ def build_filters(self, filters=None):
orm_filters.update({'shape__intersects': bounds.shape})
return orm_filters
+
+
+class PointSetResource(SluggedResource):
+ points = fields.ToManyField(
+ 'boundaryservice.resources.PointResource', 'point')
+
+ class Meta:
+ queryset = PointSet.objects.all()
+ serializer = Serializer(
+ formats=['json', 'jsonp'],
+ content_types={'json': 'application/json',
+ 'jsonp': 'text/javascript'})
+ resource_name = 'point-set'
+ excludes = ['id', 'singular', 'kind_first']
+ allowed_methods = ['get']
+ authentication = NoOpApiKeyAuthentication()
+ # throttle = AnonymousThrottle(throttle_at=100)
+
+
+class PointResource(SluggedResource):
+ set = fields.ForeignKey(PointSetResource, 'set')
+
+ class Meta:
+ queryset = Point.objects.all()
+ serializer = Serializer(
+ formats=['json', 'jsonp'],
+ content_types={'json': 'application/json',
+ 'jsonp': 'text/javascript'})
+ resource_name = 'point'
+ excludes = ['id', 'display_name']
+ allowed_methods = ['get']
+ authentication = NoOpApiKeyAuthentication()
+ # throttle = AnonymousThrottle(throttle_at=100)
+
+ def build_filters(self, filters=None):
+ """
+ Override build_filters to support geoqueries.
+ """
+ if filters is None:
+ filters = {}
+
+ orm_filters = super(PointResource, self).build_filters(filters)
+
+ if 'sets' in filters:
+ sets = filters['sets'].split(',')
+
+ orm_filters.update({'set__slug__in': sets})
+
+ if 'near' in filters:
+ lat, lon, range = filters['near'].split(',')
+ wkt_pt = 'POINT(%s %s)' % (lon, lat)
+ numeral = re.match('([0-9]+)', range).group(1)
+ unit = range[len(numeral):]
+ numeral = int(numeral)
+ kwargs = {unit: numeral}
+
+ orm_filters.update({'point__distance_lte': (wkt_pt, D(**kwargs))})
+
+ if 'intersects' in filters:
+ slug = filters['intersects']
+ bounds = Point.objects.get(slug=slug)
+
+ orm_filters.update({'point__intersects': bounds.point})
+
+ print orm_filters
+ return orm_filters
View
5 boundaryservice/urls.py
@@ -1,12 +1,15 @@
from django.conf.urls.defaults import patterns, include
from tastypie.api import Api
-from boundaryservice.resources import BoundarySetResource, BoundaryResource
+from boundaryservice.resources import (BoundarySetResource, BoundaryResource,
+ PointSetResource, PointResource)
from boundaryservice.views import external_id_redirects
v1_api = Api(api_name='1.0')
v1_api.register(BoundarySetResource())
v1_api.register(BoundaryResource())
+v1_api.register(PointSetResource())
+v1_api.register(PointResource())
urlpatterns = patterns('',
(r'^(?P<api_name>1.0)/(?P<resource_name>boundary-set)/(?P<slug>[\w\d_.-]+)'

0 comments on commit bff87a0

Please sign in to comment.
Something went wrong with that request. Please try again.