Ticket #7934: f

File f, 2.9 KB (added by lkcl, 16 years ago)
Line 
1Index: django/contrib/gis/db/models/manager.py
2===================================================================
3--- django/contrib/gis/db/models/manager.py (revision 8066)
4+++ django/contrib/gis/db/models/manager.py (working copy)
5@@ -1,5 +1,6 @@
6 from django.db.models.manager import Manager
7 from django.contrib.gis.db.models.query import GeoQuerySet
8+from django.db import connection
9
10 class GeoManager(Manager):
11 "Overrides Manager to return Geographic QuerySets."
12@@ -75,3 +76,53 @@
13
14 def unionagg(self, *args, **kwargs):
15 return self.get_query_set().unionagg(*args, **kwargs)
16+
17+ def nearest_to(self, point, number=5, geom_column='latlon',
18+ from_srid=2163, to_srid=2163,
19+ within_range=None):
20+ """finds the model objects nearest to a given point
21+
22+ `point` is a tuple of (x, y) in the spatial ref sys given by `from_srid`
23+
24+ returns a list of tuples, sorted by increasing distance from the given `point`.
25+ each tuple being (model_object, dist), where distance is in the units of the
26+ spatial ref sys given by `to_srid`"""
27+ if not isinstance(point, tuple):
28+ raise TypeError
29+ from string import Template
30+ cursor = connection.cursor()
31+ x, y = point
32+ table = self.model._meta.db_table
33+ distance_clause = ''
34+ if within_range:
35+ distance_clause = "AND (Distance(GeomFromText('POINT($x $y)', $from_srid), $geom_column) <= %f)" % within_range
36+ sql = Template("""
37+ SELECT id,
38+ Length(Transform(SetSRID(MakeLine($geom_column, GeomFromText('POINT(' || $x || ' ' || $y || ')', $from_srid)), $from_srid), $to_srid))
39+
40+
41+ FROM $table
42+ WHERE $geom_column IS NOT NULL %s
43+ ORDER BY Distance(GeomFromText('POINT($x $y)', $from_srid), $geom_column) ASC
44+ LIMIT $number;
45+ """ % distance_clause)
46+ cursor.execute(sql.substitute(locals()))
47+ nearbys = cursor.fetchall()
48+ # get a list of primary keys of the nearby model objects
49+ ids = [p[0] for p in nearbys]
50+ # get a list of distances from the model objects
51+ dists = [p[1] for p in nearbys]
52+ places = self.filter(id__in=ids)
53+ # the QuerySet comes back in an undefined order; let's
54+ # order it by distance from the given point
55+ def order_by(objects, listing, name):
56+ """a convenience method that takes a list of objects,
57+ and orders them by comparing an attribute given by `name`
58+ to a sorted listing of values of the same length."""
59+ sorted = []
60+ for i in listing:
61+ for obj in objects:
62+ if getattr(obj, name) == i:
63+ sorted.append(obj)
64+ return sorted
65+ return zip(order_by(places, ids, 'id'), dists)
Back to Top