Loading django/contrib/gis/db/backends/postgis/operations.py +35 −46 Original line number Diff line number Diff line Loading @@ -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): Loading Loading @@ -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')]) Loading @@ -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 = { Loading Loading @@ -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') Loading @@ -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. Loading @@ -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. Loading Loading @@ -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' Loading @@ -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 Loading Loading @@ -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
django/contrib/gis/db/backends/postgis/operations.py +35 −46 Original line number Diff line number Diff line Loading @@ -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): Loading Loading @@ -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')]) Loading @@ -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 = { Loading Loading @@ -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') Loading @@ -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. Loading @@ -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. Loading Loading @@ -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' Loading @@ -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 Loading Loading @@ -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