Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Reimplemented PostGIS spatial_version with cached_property

  • Loading branch information...
commit b14bd604043ba1d89493558f4f6cb7a9bcf17923 1 parent 749c2e4
@claudep claudep authored
Showing with 35 additions and 46 deletions.
  1. +35 −46 django/contrib/gis/db/backends/postgis/operations.py
View
81 django/contrib/gis/db/backends/postgis/operations.py
@@ -11,6 +11,10 @@
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 @@ def get_dist_ops(operator):
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 @@ def get_dist_ops(operator):
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 @@ def get_dist_ops(operator):
}
# 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 @@ def get_dist_ops(operator):
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 @@ def get_dist_ops(operator):
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 @@ def spatial_aggregate_sql(self, agg):
# 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
Please sign in to comment.
Something went wrong with that request. Please try again.