Reimplemented PostGIS spatial_version with cached_property
This commit is contained in:
parent
749c2e4333
commit
b14bd60404
|
@ -11,6 +11,10 @@ from django.core.exceptions import ImproperlyConfigured
|
|||
from django.db.backends.postgresql_psycopg2.base import DatabaseOperations
|
||||
from django.db.utils import DatabaseError
|
||||
from django.utils import six
|
||||
from django.utils.functional import cached_property
|
||||
|
||||
from .models import GeometryColumns, SpatialRefSys
|
||||
|
||||
|
||||
#### Classes used in constructing PostGIS spatial SQL ####
|
||||
class PostGISOperator(SpatialOperation):
|
||||
|
@ -62,6 +66,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
compiler_module = 'django.contrib.gis.db.models.sql.compiler'
|
||||
name = 'postgis'
|
||||
postgis = True
|
||||
geom_func_prefix = 'ST_'
|
||||
version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)')
|
||||
valid_aggregates = dict([(k, None) for k in
|
||||
('Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union')])
|
||||
|
@ -72,45 +77,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
def __init__(self, connection):
|
||||
super(PostGISOperations, self).__init__(connection)
|
||||
|
||||
# Trying to get the PostGIS version because the function
|
||||
# signatures will depend on the version used. The cost
|
||||
# here is a database query to determine the version, which
|
||||
# can be mitigated by setting `POSTGIS_VERSION` with a 3-tuple
|
||||
# comprising user-supplied values for the major, minor, and
|
||||
# subminor revision of PostGIS.
|
||||
try:
|
||||
if hasattr(settings, 'POSTGIS_VERSION'):
|
||||
vtup = settings.POSTGIS_VERSION
|
||||
if len(vtup) == 3:
|
||||
# The user-supplied PostGIS version.
|
||||
version = vtup
|
||||
else:
|
||||
# This was the old documented way, but it's stupid to
|
||||
# include the string.
|
||||
version = vtup[1:4]
|
||||
else:
|
||||
vtup = self.postgis_version_tuple()
|
||||
version = vtup[1:]
|
||||
|
||||
# Getting the prefix -- even though we don't officially support
|
||||
# PostGIS 1.2 anymore, keeping it anyway in case a prefix change
|
||||
# for something else is necessary.
|
||||
if version >= (1, 2, 2):
|
||||
prefix = 'ST_'
|
||||
else:
|
||||
prefix = ''
|
||||
|
||||
self.geom_func_prefix = prefix
|
||||
self.spatial_version = version
|
||||
except DatabaseError:
|
||||
raise ImproperlyConfigured(
|
||||
'Cannot determine PostGIS version for database "%s". '
|
||||
'GeoDjango requires at least PostGIS version 1.3. '
|
||||
'Was the database created from a spatial database '
|
||||
'template?' % self.connection.settings_dict['NAME']
|
||||
)
|
||||
# TODO: Raise helpful exceptions as they become known.
|
||||
|
||||
prefix = self.geom_func_prefix
|
||||
# PostGIS-specific operators. The commented descriptions of these
|
||||
# operators come from Section 7.6 of the PostGIS 1.4 documentation.
|
||||
self.geometry_operators = {
|
||||
|
@ -188,13 +155,13 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
self.geometry_functions.update(self.distance_functions)
|
||||
|
||||
# Only PostGIS versions 1.3.4+ have GeoJSON serialization support.
|
||||
if version < (1, 3, 4):
|
||||
if self.spatial_version < (1, 3, 4):
|
||||
GEOJSON = False
|
||||
else:
|
||||
GEOJSON = prefix + 'AsGeoJson'
|
||||
|
||||
# ST_ContainsProperly ST_MakeLine, and ST_GeoHash added in 1.4.
|
||||
if version >= (1, 4, 0):
|
||||
if self.spatial_version >= (1, 4, 0):
|
||||
GEOHASH = 'ST_GeoHash'
|
||||
BOUNDINGCIRCLE = 'ST_MinimumBoundingCircle'
|
||||
self.geometry_functions['contains_properly'] = PostGISFunction(prefix, 'ContainsProperly')
|
||||
|
@ -202,7 +169,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
GEOHASH, BOUNDINGCIRCLE = False, False
|
||||
|
||||
# Geography type support added in 1.5.
|
||||
if version >= (1, 5, 0):
|
||||
if self.spatial_version >= (1, 5, 0):
|
||||
self.geography = True
|
||||
# Only a subset of the operators and functions are available
|
||||
# for the geography type.
|
||||
|
@ -217,7 +184,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
}
|
||||
|
||||
# Native geometry type support added in PostGIS 2.0.
|
||||
if version >= (2, 0, 0):
|
||||
if self.spatial_version >= (2, 0, 0):
|
||||
self.geometry = True
|
||||
|
||||
# Creating a dictionary lookup of all GIS terms for PostGIS.
|
||||
|
@ -260,7 +227,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
self.union = prefix + 'Union'
|
||||
self.unionagg = prefix + 'Union'
|
||||
|
||||
if version >= (2, 0, 0):
|
||||
if self.spatial_version >= (2, 0, 0):
|
||||
self.extent3d = prefix + '3DExtent'
|
||||
self.length3d = prefix + '3DLength'
|
||||
self.perimeter3d = prefix + '3DPerimeter'
|
||||
|
@ -269,6 +236,30 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
self.length3d = prefix + 'Length3D'
|
||||
self.perimeter3d = prefix + 'Perimeter3D'
|
||||
|
||||
@cached_property
|
||||
def spatial_version(self):
|
||||
"""Determine the version of the PostGIS library."""
|
||||
# Trying to get the PostGIS version because the function
|
||||
# signatures will depend on the version used. The cost
|
||||
# here is a database query to determine the version, which
|
||||
# can be mitigated by setting `POSTGIS_VERSION` with a 3-tuple
|
||||
# comprising user-supplied values for the major, minor, and
|
||||
# subminor revision of PostGIS.
|
||||
if hasattr(settings, 'POSTGIS_VERSION'):
|
||||
version = settings.POSTGIS_VERSION
|
||||
else:
|
||||
try:
|
||||
vtup = self.postgis_version_tuple()
|
||||
except DatabaseError:
|
||||
raise ImproperlyConfigured(
|
||||
'Cannot determine PostGIS version for database "%s". '
|
||||
'GeoDjango requires at least PostGIS version 1.3. '
|
||||
'Was the database created from a spatial database '
|
||||
'template?' % self.connection.settings_dict['NAME']
|
||||
)
|
||||
version = vtup[1:]
|
||||
return version
|
||||
|
||||
def check_aggregate_support(self, aggregate):
|
||||
"""
|
||||
Checks if the given aggregate name is supported (that is, if it's
|
||||
|
@ -572,9 +563,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||
|
||||
# Routines for getting the OGC-compliant models.
|
||||
def geometry_columns(self):
|
||||
from django.contrib.gis.db.backends.postgis.models import GeometryColumns
|
||||
return GeometryColumns
|
||||
|
||||
def spatial_ref_sys(self):
|
||||
from django.contrib.gis.db.backends.postgis.models import SpatialRefSys
|
||||
return SpatialRefSys
|
||||
|
|
Loading…
Reference in New Issue