1
0
mirror of https://github.com/django/django.git synced 2025-03-12 10:22:37 +00:00

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
This commit is contained in:
Justin Bronn 2009-04-10 18:08:37 +00:00
parent da17a314ca
commit ae7cb577dd
4 changed files with 47 additions and 98 deletions

View File

@ -48,6 +48,11 @@ class SpatialRefSys(models.Model):
ref_sys_name = models.CharField(max_length=256) ref_sys_name = models.CharField(max_length=256)
proj4text = models.CharField(max_length=2048) proj4text = models.CharField(max_length=2048)
@property
def wkt(self):
from django.contrib.gis.gdal import SpatialReference
return SpatialReference(self.proj4text).wkt
class Meta: class Meta:
abstract = True abstract = True
db_table = 'spatial_ref_sys' db_table = 'spatial_ref_sys'

View File

@ -4,18 +4,30 @@ from django.contrib.gis.db.backend import SpatialBackend, gqn
# GeometryProxy, GEOS, and Distance imports. # GeometryProxy, GEOS, and Distance imports.
from django.contrib.gis.db.models.proxy import GeometryProxy from django.contrib.gis.db.models.proxy import GeometryProxy
from django.contrib.gis.measure import Distance 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. # 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. # 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): class GeometryField(SpatialBackend.Field):
"The base GIS field -- maps to the OpenGIS Specification Geometry type." "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. # easily available in the field instance for distance queries.
self.srid = srid 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. # Setting the dimension of the geometry field.
self.dim = dim self.dim = dim
@ -63,28 +72,29 @@ class GeometryField(SpatialBackend.Field):
super(GeometryField, self).__init__(**kwargs) # Calling the parent initializtion function super(GeometryField, self).__init__(**kwargs) # Calling the parent initializtion function
def _populate_srid_info(self): # The following properties are used to get the units, their name, and
if self.srid not in SRID_CACHE: # the spheroid corresponding to the SRID of the GeometryField.
SRID_CACHE[self.srid] = get_srid_info(self.srid) def _get_srid_info(self):
self._units_cache, self._units_name_cache, self._spheroid_cache = SRID_CACHE[self.srid] # Get attributes from `get_srid_info`.
self._units, self._units_name, self._spheroid = get_srid_info(self.srid)
def _get_units(self): @property
if self._units_cache is None: def spheroid(self):
self._populate_srid_info() if not hasattr(self, '_spheroid'):
return self._units_cache self._get_srid_info()
units = property(_get_units) return self._spheroid
def _get_units_name(self): @property
if self._units_name_cache is None: def units(self):
self._populate_srid_info() if not hasattr(self, '_units'):
return self._units_name_cache self._get_srid_info()
units_name = property(_get_units_name) return self._units
def _get_spheroid(self): @property
if self._spheroid_cache is None: def units_name(self):
self._populate_srid_info() if not hasattr(self, '_units_name'):
return self._spheroid_cache self._get_srid_info()
_spheroid = property(_get_spheroid) return self._units_name
# The following properties are for formerly private variables that are now # The following properties are for formerly private variables that are now
# public for GeometryField. Because of their use by third-party applications, # public for GeometryField. Because of their use by third-party applications,

View File

@ -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.backend import SpatialBackend
from django.contrib.gis.db.models import aggregates 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.db.models.sql import AreaField, DistanceField, GeomField, GeoQuery, GeoWhereNode
from django.contrib.gis.measure import Area, Distance from django.contrib.gis.measure import Area, Distance
from django.contrib.gis.models import get_srid_info
class GeoQuerySet(QuerySet): class GeoQuerySet(QuerySet):
"The Geographic QuerySet." "The Geographic QuerySet."

View File

@ -214,14 +214,6 @@ class SpatialRefSysMixin(object):
except: except:
return unicode(self.wkt) 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 # Django test suite on 2.3 platforms will choke on code inside this
# conditional. # conditional.
if not PYTHON23: if not PYTHON23:
@ -237,62 +229,5 @@ if not PYTHON23:
class SpatialRefSys(SpatialBackend.SpatialRefSys, SpatialRefSysMixin): class SpatialRefSys(SpatialBackend.SpatialRefSys, SpatialRefSysMixin):
pass pass
GeometryColumns = SpatialBackend.GeometryColumns 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: except:
pass pass