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:
parent
da17a314ca
commit
ae7cb577dd
@ -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'
|
||||||
|
@ -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,
|
||||||
|
@ -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."
|
||||||
|
@ -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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user