Author: jbronn
Date: 2010-01-18 15:49:13 -0600 (Mon, 18 Jan 2010)
New Revision: 12258

Modified:
   django/trunk/django/contrib/gis/db/backends/base.py
   django/trunk/django/contrib/gis/db/models/fields.py
Log:
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.


Modified: django/trunk/django/contrib/gis/db/backends/base.py
===================================================================
--- django/trunk/django/contrib/gis/db/backends/base.py 2010-01-18 21:02:47 UTC 
(rev 12257)
+++ django/trunk/django/contrib/gis/db/backends/base.py 2010-01-18 21:49:13 UTC 
(rev 12258)
@@ -122,6 +122,13 @@
     def spatial_lookup_sql(self, lvalue, lookup_type, value, field):
         raise NotImplmentedError
 
+    # Routines for getting the OGC-compliant models.
+    def geometry_columns(self):
+        raise NotImplementedError
+
+    def spatial_ref_sys(self):
+        raise NotImplementedError
+
 class SpatialRefSysMixin(object):
     """
     The SpatialRefSysMixin is a class used by the database-dependent

Modified: django/trunk/django/contrib/gis/db/models/fields.py
===================================================================
--- django/trunk/django/contrib/gis/db/models/fields.py 2010-01-18 21:02:47 UTC 
(rev 12257)
+++ django/trunk/django/contrib/gis/db/models/fields.py 2010-01-18 21:49:13 UTC 
(rev 12258)
@@ -1,45 +1,42 @@
 from django.db.models.fields import Field
+from django.db.models.sql.expressions import SQLEvaluator
 from django.utils.translation import ugettext_lazy as _
 from django.contrib.gis import forms
 from django.contrib.gis.db.models.proxy import GeometryProxy
 from django.contrib.gis.geometry.backend import Geometry, GeometryException
-from django.contrib.gis.measure import Distance
-from django.db.models.sql.expressions import SQLEvaluator
 
-# Local cache of the spatial_ref_sys table, which holds static data.
-# This exists so that we don't have to hit the database each time
-# we construct a distance query.
-_srid_cache = {'postgis' : {},
-               'oracle' : {},
-               'spatialite' : {},
-               }
+# Local cache of the spatial_ref_sys table, which holds SRID data for each
+# spatial database alias. This cache exists so that the database isn't queried
+# for SRID info each time a distance query is constructed.
+_srid_cache = {}
 
 def get_srid_info(srid, connection):
     """
     Returns the units, unit name, and spheroid WKT associated with the
     given SRID from the `spatial_ref_sys` (or equivalent) spatial database
-    table.  These results are cached.
+    table for the given database connection.  These results are cached.
     """
     global _srid_cache
 
-    # No `spatial_ref_sys` table in MySQL.
-    if connection.ops.mysql:
+    try:
+        # The SpatialRefSys model for the spatial backend.
+        SpatialRefSys = connection.ops.spatial_ref_sys()
+    except NotImplementedError:
+        # No `spatial_ref_sys` table in spatial backend (e.g., MySQL).
         return None, None, None
 
-    name = connection.ops.name
-    if not srid in _srid_cache[name]:
-        if connection.ops.postgis:
-            from django.contrib.gis.db.backends.postgis.models import 
SpatialRefSys
-        elif connection.ops.oracle:
-            from django.contrib.gis.db.backends.oracle.models import 
SpatialRefSys
-        elif connection.ops.spatialite:
-            from django.contrib.gis.db.backends.spatialite.models import 
SpatialRefSys
-        sr = SpatialRefSys.objects.get(srid=srid)
+    if not connection.alias in _srid_cache:
+        # Initialize SRID dictionary for database if it doesn't exist.
+        _srid_cache[connection.alias] = {}
+
+    if not srid in _srid_cache[connection.alias]:
+        # Use `SpatialRefSys` model to query for spatial reference info.
+        sr = SpatialRefSys.objects.using(connection.alias).get(srid=srid)
         units, units_name = sr.units
         spheroid = SpatialRefSys.get_spheroid(sr.wkt)
-        _srid_cache[name][srid] = (units, units_name, spheroid)
+        _srid_cache[connection.alias][srid] = (units, units_name, spheroid)
 
-    return _srid_cache[name][srid]
+    return _srid_cache[connection.alias][srid]
 
 class GeometryField(Field):
     "The base GIS field -- maps to the OpenGIS Specification Geometry type."
@@ -141,31 +138,6 @@
         """
         return connection.ops.get_distance(self, value, lookup_type)
 
-        if isinstance(dist, Distance):
-            if self.geodetic(connection):
-                # Won't allow Distance objects w/DWithin lookups on PostGIS.
-                if connection.ops.postgis and lookup_type == 'dwithin':
-                    raise ValueError('Only numeric values of degree units are 
allowed on geographic DWithin queries.')
-
-                # Spherical distance calculation parameter should be in meters.
-                dist_param = dist.m
-            else:
-                dist_param = getattr(dist, 
Distance.unit_attname(self.units_name(connection)))
-        else:
-            # Assuming the distance is in the units of the field.
-            dist_param = dist
-
-        if connection.ops.oracle and lookup_type == 'dwithin':
-            dist_param = 'distance=%s' % dist_param
-
-        if connection.ops.postgis and self.geodetic(connection) and 
lookup_type != 'dwithin' and option == 'spheroid':
-            # On PostGIS, by default `ST_distance_sphere` is used; but if the
-            # accuracy of `ST_distance_spheroid` is needed than the spheroid
-            # needs to be passed to the SQL stored procedure.
-            return [self._spheroid, dist_param]
-        else:
-            return [dist_param]
-
     def get_prep_value(self, value):
         """
         Spatial lookup values are either a parameter that is (or may be

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/django-updates?hl=en.


Reply via email to