Commit ae7cb577 authored by Justin Bronn's avatar Justin Bronn
Browse files

Refactored `get_srid_info` to use the ORM (now possible since it's no longer...

Refactored `get_srid_info` to use the ORM (now possible since it's no longer used in `GeometryField.__init__`), and moved to `fields` module; removed unnecessary code.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@10493 bcc190cf-cafb-0310-a4f2-bffc1f526a37
parent da17a314
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -48,6 +48,11 @@ class SpatialRefSys(models.Model):
    ref_sys_name = models.CharField(max_length=256)
    proj4text = models.CharField(max_length=2048)

    @property
    def wkt(self):
        from django.contrib.gis.gdal import SpatialReference
        return SpatialReference(self.proj4text).wkt
    
    class Meta:
        abstract = True
        db_table = 'spatial_ref_sys'
+44 −34
Original line number Diff line number Diff line
@@ -4,18 +4,30 @@ from django.contrib.gis.db.backend import SpatialBackend, gqn
# GeometryProxy, GEOS, and Distance imports.
from django.contrib.gis.db.models.proxy import GeometryProxy
from django.contrib.gis.measure import Distance
# The `get_srid_info` function gets SRID information from the spatial
# reference system table w/o using the ORM.
from django.contrib.gis.models import get_srid_info

def deprecated_property(func):
    from warnings import warn
    warn('This attribute has been deprecated, please use "%s" instead.' % func.__name__[1:])
    return property(func)

# 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.
SRID_CACHE = {}
_srid_cache = {}

def get_srid_info(srid):
    """
    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.
    """
    global _srid_cache

    if SpatialBackend.mysql:
        return None, None, None

    if not srid in _srid_cache:
        from django.contrib.gis.models import SpatialRefSys
        sr = SpatialRefSys.objects.get(srid=srid)
        units, units_name = sr.units
        spheroid = SpatialRefSys.get_spheroid(sr.wkt)
        _srid_cache[srid] = (units, units_name, spheroid)

    return _srid_cache[srid]

class GeometryField(SpatialBackend.Field):
    "The base GIS field -- maps to the OpenGIS Specification Geometry type."
@@ -51,9 +63,6 @@ class GeometryField(SpatialBackend.Field):
        # easily available in the field instance for distance queries.
        self.srid = srid

        # units_cache, units_name_cache and _spheroid_cache are lazily loaded.
        self._units_cache = self._units_name_cache = self._spheroid_cache = None

        # Setting the dimension of the geometry field.
        self.dim = dim

@@ -63,28 +72,29 @@ class GeometryField(SpatialBackend.Field):

        super(GeometryField, self).__init__(**kwargs) # Calling the parent initializtion function

    def _populate_srid_info(self):
        if self.srid not in SRID_CACHE:
            SRID_CACHE[self.srid] = get_srid_info(self.srid)
        self._units_cache, self._units_name_cache, self._spheroid_cache = SRID_CACHE[self.srid]

    def _get_units(self):
        if self._units_cache is None:
            self._populate_srid_info()
        return self._units_cache
    units = property(_get_units)

    def _get_units_name(self):
        if self._units_name_cache is None:
            self._populate_srid_info()
        return self._units_name_cache
    units_name = property(_get_units_name)

    def _get_spheroid(self):
        if self._spheroid_cache is None:
            self._populate_srid_info()
        return self._spheroid_cache
    _spheroid = property(_get_spheroid)
    # The following properties are used to get the units, their name, and
    # the spheroid corresponding to the SRID of the GeometryField.
    def _get_srid_info(self):
        # Get attributes from `get_srid_info`.
        self._units, self._units_name, self._spheroid = get_srid_info(self.srid)

    @property
    def spheroid(self):
        if not hasattr(self, '_spheroid'):
            self._get_srid_info()
        return self._spheroid

    @property
    def units(self):
        if not hasattr(self, '_units'):
            self._get_srid_info()
        return self._units

    @property
    def units_name(self):
        if not hasattr(self, '_units_name'):
            self._get_srid_info()
        return self._units_name

    # The following properties are for formerly private variables that are now
    # public for GeometryField.  Because of their use by third-party applications,
+1 −2
Original line number Diff line number Diff line
@@ -4,10 +4,9 @@ from django.db.models.query import QuerySet, Q, ValuesQuerySet, ValuesListQueryS

from django.contrib.gis.db.backend import SpatialBackend
from django.contrib.gis.db.models import aggregates
from django.contrib.gis.db.models.fields import GeometryField, PointField
from django.contrib.gis.db.models.fields import get_srid_info, GeometryField, PointField
from django.contrib.gis.db.models.sql import AreaField, DistanceField, GeomField, GeoQuery, GeoWhereNode
from django.contrib.gis.measure import Area, Distance
from django.contrib.gis.models import get_srid_info

class GeoQuerySet(QuerySet):
    "The Geographic QuerySet."
+0 −65
Original line number Diff line number Diff line
@@ -214,14 +214,6 @@ class SpatialRefSysMixin(object):
        except:
            return unicode(self.wkt)

# Defining dummy default first; if spatial db, will overrride.
def get_srid_info(srid):
    """
    Dummy routine for the backends that do not have the OGC required
    spatial metadata tables (like MySQL).
    """
    return None, None, None

# Django test suite on 2.3 platforms will choke on code inside this
# conditional.
if not PYTHON23:
@@ -237,62 +229,5 @@ if not PYTHON23:
        class SpatialRefSys(SpatialBackend.SpatialRefSys, SpatialRefSysMixin):
            pass
        GeometryColumns = SpatialBackend.GeometryColumns

        # Override `get_srid_info` with something real thing.
        def get_srid_info(srid):
            """
            Returns the units, unit name, and spheroid WKT associated with the
            given SRID from the `spatial_ref_sys` (or equivalent) spatial database
            table.  We use a database cursor to execute the query because this
            function is used when it is not possible to use the ORM (for example,
            during field initialization).
            """
            # SRID=-1 is a common convention for indicating the geometry has no
            # spatial reference information associated with it.  Thus, we will
            # return all None values without raising an exception.
            if srid == -1: return None, None, None

            # Getting the spatial reference WKT associated with the SRID from the
            # `spatial_ref_sys` (or equivalent) spatial database table. This query
            # cannot be executed using the ORM because this information is needed
            # when the ORM cannot be used (e.g., during the initialization of
            # `GeometryField`).
            from django.db import connection
            cur = connection.cursor()
            qn = connection.ops.quote_name
            stmt = 'SELECT %(table)s.%(wkt_col)s FROM %(table)s WHERE (%(table)s.%(srid_col)s = %(srid)s)'
            params = {'table' : qn(SpatialRefSys._meta.db_table),
                      'srid_col' : qn('srid'),
                      'srid' : srid,
                      }
            if SpatialBackend.spatialite:
                if not HAS_GDAL: raise Exception('GDAL is required to use the SpatiaLite backend.')
                params['wkt_col'] = 'proj4text'
            else:
                params['wkt_col'] = qn(SpatialRefSys.wkt_col())

            # Executing the SQL statement.
            cur.execute(stmt % params)

            # Fetching the WKT from the cursor; if the query failed raise an Exception.
            fetched = cur.fetchone()
            if not fetched:
                raise ValueError('Failed to find spatial reference entry in "%s" corresponding to SRID=%s.' %
                                 (SpatialRefSys._meta.db_table, srid))

            if SpatialBackend.spatialite:
                # Because the `spatial_ref_sys` table does _not_ contain a WKT column,
                # we have to use GDAL to determine the units from the PROJ.4 string.
                srs_wkt = SpatialReference(fetched[0]).wkt
            else:
                srs_wkt = fetched[0]
            connection.close()

            # Getting metadata associated with the spatial reference system identifier.
            # Specifically, getting the unit information and spheroid information
            # (both required for distance queries).
            unit, unit_name = SpatialRefSys.get_units(srs_wkt)
            spheroid = SpatialRefSys.get_spheroid(srs_wkt)
            return unit, unit_name, spheroid
    except:
        pass