mirror of
https://github.com/django/django.git
synced 2025-03-31 19:46:42 +00:00
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.backends.postgresql_psycopg2.base import DatabaseOperations
|
||||||
from django.db.utils import DatabaseError
|
from django.db.utils import DatabaseError
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
|
from django.utils.functional import cached_property
|
||||||
|
|
||||||
|
from .models import GeometryColumns, SpatialRefSys
|
||||||
|
|
||||||
|
|
||||||
#### Classes used in constructing PostGIS spatial SQL ####
|
#### Classes used in constructing PostGIS spatial SQL ####
|
||||||
class PostGISOperator(SpatialOperation):
|
class PostGISOperator(SpatialOperation):
|
||||||
@ -62,6 +66,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||||||
compiler_module = 'django.contrib.gis.db.models.sql.compiler'
|
compiler_module = 'django.contrib.gis.db.models.sql.compiler'
|
||||||
name = 'postgis'
|
name = 'postgis'
|
||||||
postgis = True
|
postgis = True
|
||||||
|
geom_func_prefix = 'ST_'
|
||||||
version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)')
|
version_regex = re.compile(r'^(?P<major>\d)\.(?P<minor1>\d)\.(?P<minor2>\d+)')
|
||||||
valid_aggregates = dict([(k, None) for k in
|
valid_aggregates = dict([(k, None) for k in
|
||||||
('Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union')])
|
('Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union')])
|
||||||
@ -72,45 +77,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||||||
def __init__(self, connection):
|
def __init__(self, connection):
|
||||||
super(PostGISOperations, self).__init__(connection)
|
super(PostGISOperations, self).__init__(connection)
|
||||||
|
|
||||||
# Trying to get the PostGIS version because the function
|
prefix = self.geom_func_prefix
|
||||||
# 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.
|
|
||||||
|
|
||||||
# PostGIS-specific operators. The commented descriptions of these
|
# PostGIS-specific operators. The commented descriptions of these
|
||||||
# operators come from Section 7.6 of the PostGIS 1.4 documentation.
|
# operators come from Section 7.6 of the PostGIS 1.4 documentation.
|
||||||
self.geometry_operators = {
|
self.geometry_operators = {
|
||||||
@ -188,13 +155,13 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||||||
self.geometry_functions.update(self.distance_functions)
|
self.geometry_functions.update(self.distance_functions)
|
||||||
|
|
||||||
# Only PostGIS versions 1.3.4+ have GeoJSON serialization support.
|
# Only PostGIS versions 1.3.4+ have GeoJSON serialization support.
|
||||||
if version < (1, 3, 4):
|
if self.spatial_version < (1, 3, 4):
|
||||||
GEOJSON = False
|
GEOJSON = False
|
||||||
else:
|
else:
|
||||||
GEOJSON = prefix + 'AsGeoJson'
|
GEOJSON = prefix + 'AsGeoJson'
|
||||||
|
|
||||||
# ST_ContainsProperly ST_MakeLine, and ST_GeoHash added in 1.4.
|
# 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'
|
GEOHASH = 'ST_GeoHash'
|
||||||
BOUNDINGCIRCLE = 'ST_MinimumBoundingCircle'
|
BOUNDINGCIRCLE = 'ST_MinimumBoundingCircle'
|
||||||
self.geometry_functions['contains_properly'] = PostGISFunction(prefix, 'ContainsProperly')
|
self.geometry_functions['contains_properly'] = PostGISFunction(prefix, 'ContainsProperly')
|
||||||
@ -202,7 +169,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||||||
GEOHASH, BOUNDINGCIRCLE = False, False
|
GEOHASH, BOUNDINGCIRCLE = False, False
|
||||||
|
|
||||||
# Geography type support added in 1.5.
|
# Geography type support added in 1.5.
|
||||||
if version >= (1, 5, 0):
|
if self.spatial_version >= (1, 5, 0):
|
||||||
self.geography = True
|
self.geography = True
|
||||||
# Only a subset of the operators and functions are available
|
# Only a subset of the operators and functions are available
|
||||||
# for the geography type.
|
# for the geography type.
|
||||||
@ -217,7 +184,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Native geometry type support added in PostGIS 2.0.
|
# Native geometry type support added in PostGIS 2.0.
|
||||||
if version >= (2, 0, 0):
|
if self.spatial_version >= (2, 0, 0):
|
||||||
self.geometry = True
|
self.geometry = True
|
||||||
|
|
||||||
# Creating a dictionary lookup of all GIS terms for PostGIS.
|
# Creating a dictionary lookup of all GIS terms for PostGIS.
|
||||||
@ -260,7 +227,7 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||||||
self.union = prefix + 'Union'
|
self.union = prefix + 'Union'
|
||||||
self.unionagg = prefix + 'Union'
|
self.unionagg = prefix + 'Union'
|
||||||
|
|
||||||
if version >= (2, 0, 0):
|
if self.spatial_version >= (2, 0, 0):
|
||||||
self.extent3d = prefix + '3DExtent'
|
self.extent3d = prefix + '3DExtent'
|
||||||
self.length3d = prefix + '3DLength'
|
self.length3d = prefix + '3DLength'
|
||||||
self.perimeter3d = prefix + '3DPerimeter'
|
self.perimeter3d = prefix + '3DPerimeter'
|
||||||
@ -269,6 +236,30 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations):
|
|||||||
self.length3d = prefix + 'Length3D'
|
self.length3d = prefix + 'Length3D'
|
||||||
self.perimeter3d = prefix + 'Perimeter3D'
|
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):
|
def check_aggregate_support(self, aggregate):
|
||||||
"""
|
"""
|
||||||
Checks if the given aggregate name is supported (that is, if it's
|
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.
|
# Routines for getting the OGC-compliant models.
|
||||||
def geometry_columns(self):
|
def geometry_columns(self):
|
||||||
from django.contrib.gis.db.backends.postgis.models import GeometryColumns
|
|
||||||
return GeometryColumns
|
return GeometryColumns
|
||||||
|
|
||||||
def spatial_ref_sys(self):
|
def spatial_ref_sys(self):
|
||||||
from django.contrib.gis.db.backends.postgis.models import SpatialRefSys
|
|
||||||
return SpatialRefSys
|
return SpatialRefSys
|
||||||
|
Loading…
x
Reference in New Issue
Block a user