Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed problems associated with the `GeometryField` SRID cache: it is …

…now keyed by the connection alias rather than the spatial backend name (e.g., `spatial_ref_sys` tables may have different entries, even if backend is the same), explicitly pass in connection alias to `SpatialRefSys` query to ensure correct entry is retrieved, and removed unused code from `GeometryField.get_distance`. Thanks, Josh Livni, for the bug report.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@12258 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 6b659270d6813029c7d482bec68c623525471f0b 1 parent a1fbc0d
Justin Bronn authored January 18, 2010
7  django/contrib/gis/db/backends/base.py
@@ -122,6 +122,13 @@ def spatial_aggregate_sql(self, agg):
122 122
     def spatial_lookup_sql(self, lvalue, lookup_type, value, field):
123 123
         raise NotImplmentedError
124 124
 
  125
+    # Routines for getting the OGC-compliant models.
  126
+    def geometry_columns(self):
  127
+        raise NotImplementedError
  128
+
  129
+    def spatial_ref_sys(self):
  130
+        raise NotImplementedError
  131
+
125 132
 class SpatialRefSysMixin(object):
126 133
     """
127 134
     The SpatialRefSysMixin is a class used by the database-dependent
68  django/contrib/gis/db/models/fields.py
... ...
@@ -1,45 +1,42 @@
1 1
 from django.db.models.fields import Field
  2
+from django.db.models.sql.expressions import SQLEvaluator
2 3
 from django.utils.translation import ugettext_lazy as _
3 4
 from django.contrib.gis import forms
4 5
 from django.contrib.gis.db.models.proxy import GeometryProxy
5 6
 from django.contrib.gis.geometry.backend import Geometry, GeometryException
6  
-from django.contrib.gis.measure import Distance
7  
-from django.db.models.sql.expressions import SQLEvaluator
8 7
 
9  
-# Local cache of the spatial_ref_sys table, which holds static data.
10  
-# This exists so that we don't have to hit the database each time
11  
-# we construct a distance query.
12  
-_srid_cache = {'postgis' : {},
13  
-               'oracle' : {},
14  
-               'spatialite' : {},
15  
-               }
  8
+# Local cache of the spatial_ref_sys table, which holds SRID data for each
  9
+# spatial database alias. This cache exists so that the database isn't queried
  10
+# for SRID info each time a distance query is constructed.
  11
+_srid_cache = {}
16 12
 
17 13
 def get_srid_info(srid, connection):
18 14
     """
19 15
     Returns the units, unit name, and spheroid WKT associated with the
20 16
     given SRID from the `spatial_ref_sys` (or equivalent) spatial database
21  
-    table.  These results are cached.
  17
+    table for the given database connection.  These results are cached.
22 18
     """
23 19
     global _srid_cache
24 20
 
25  
-    # No `spatial_ref_sys` table in MySQL.
26  
-    if connection.ops.mysql:
  21
+    try:
  22
+        # The SpatialRefSys model for the spatial backend.
  23
+        SpatialRefSys = connection.ops.spatial_ref_sys()
  24
+    except NotImplementedError:
  25
+        # No `spatial_ref_sys` table in spatial backend (e.g., MySQL).
27 26
         return None, None, None
28 27
 
29  
-    name = connection.ops.name
30  
-    if not srid in _srid_cache[name]:
31  
-        if connection.ops.postgis:
32  
-            from django.contrib.gis.db.backends.postgis.models import SpatialRefSys
33  
-        elif connection.ops.oracle:
34  
-            from django.contrib.gis.db.backends.oracle.models import SpatialRefSys
35  
-        elif connection.ops.spatialite:
36  
-            from django.contrib.gis.db.backends.spatialite.models import SpatialRefSys
37  
-        sr = SpatialRefSys.objects.get(srid=srid)
  28
+    if not connection.alias in _srid_cache:
  29
+        # Initialize SRID dictionary for database if it doesn't exist.
  30
+        _srid_cache[connection.alias] = {}
  31
+
  32
+    if not srid in _srid_cache[connection.alias]:
  33
+        # Use `SpatialRefSys` model to query for spatial reference info.
  34
+        sr = SpatialRefSys.objects.using(connection.alias).get(srid=srid)
38 35
         units, units_name = sr.units
39 36
         spheroid = SpatialRefSys.get_spheroid(sr.wkt)
40  
-        _srid_cache[name][srid] = (units, units_name, spheroid)
  37
+        _srid_cache[connection.alias][srid] = (units, units_name, spheroid)
41 38
 
42  
-    return _srid_cache[name][srid]
  39
+    return _srid_cache[connection.alias][srid]
43 40
 
44 41
 class GeometryField(Field):
45 42
     "The base GIS field -- maps to the OpenGIS Specification Geometry type."
@@ -141,31 +138,6 @@ def get_distance(self, value, lookup_type, connection):
141 138
         """
142 139
         return connection.ops.get_distance(self, value, lookup_type)
143 140
 
144  
-        if isinstance(dist, Distance):
145  
-            if self.geodetic(connection):
146  
-                # Won't allow Distance objects w/DWithin lookups on PostGIS.
147  
-                if connection.ops.postgis and lookup_type == 'dwithin':
148  
-                    raise ValueError('Only numeric values of degree units are allowed on geographic DWithin queries.')
149  
-
150  
-                # Spherical distance calculation parameter should be in meters.
151  
-                dist_param = dist.m
152  
-            else:
153  
-                dist_param = getattr(dist, Distance.unit_attname(self.units_name(connection)))
154  
-        else:
155  
-            # Assuming the distance is in the units of the field.
156  
-            dist_param = dist
157  
-
158  
-        if connection.ops.oracle and lookup_type == 'dwithin':
159  
-            dist_param = 'distance=%s' % dist_param
160  
-
161  
-        if connection.ops.postgis and self.geodetic(connection) and lookup_type != 'dwithin' and option == 'spheroid':
162  
-            # On PostGIS, by default `ST_distance_sphere` is used; but if the
163  
-            # accuracy of `ST_distance_spheroid` is needed than the spheroid
164  
-            # needs to be passed to the SQL stored procedure.
165  
-            return [self._spheroid, dist_param]
166  
-        else:
167  
-            return [dist_param]
168  
-
169 141
     def get_prep_value(self, value):
170 142
         """
171 143
         Spatial lookup values are either a parameter that is (or may be

0 notes on commit 6b65927

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