diff --git a/django/contrib/gis/db/backends/base/operations.py b/django/contrib/gis/db/backends/base/operations.py index 56f1f6c61e..4365b64542 100644 --- a/django/contrib/gis/db/backends/base/operations.py +++ b/django/contrib/gis/db/backends/base/operations.py @@ -102,6 +102,11 @@ class BaseSpatialOperations(object): """ raise NotImplementedError('subclasses of BaseSpatialOperations must provide a geo_db_placeholder() method') + def check_aggregate_support(self, aggregate): + if aggregate.contains_aggregate == 'gis': + return aggregate.name in self.valid_aggregates + return super(BaseSpatialOperations, self).check_aggregate_support(aggregate) + # Spatial SQL Construction def spatial_aggregate_sql(self, agg): raise NotImplementedError('Aggregate support not implemented for this spatial backend.') diff --git a/django/contrib/gis/db/backends/mysql/operations.py b/django/contrib/gis/db/backends/mysql/operations.py index 18dcca458d..6e76674364 100644 --- a/django/contrib/gis/db/backends/mysql/operations.py +++ b/django/contrib/gis/db/backends/mysql/operations.py @@ -4,7 +4,7 @@ from django.contrib.gis.db.backends.utils import SpatialOperator from django.db.backends.mysql.operations import DatabaseOperations -class MySQLOperations(DatabaseOperations, BaseSpatialOperations): +class MySQLOperations(BaseSpatialOperations, DatabaseOperations): mysql = True name = 'mysql' diff --git a/django/contrib/gis/db/backends/oracle/operations.py b/django/contrib/gis/db/backends/oracle/operations.py index 5f371555a6..f6ef5415e2 100644 --- a/django/contrib/gis/db/backends/oracle/operations.py +++ b/django/contrib/gis/db/backends/oracle/operations.py @@ -52,7 +52,7 @@ class SDORelate(SpatialOperator): return super(SDORelate, self).as_sql(connection, lookup, template_params, sql_params) -class OracleOperations(DatabaseOperations, BaseSpatialOperations): +class OracleOperations(BaseSpatialOperations, DatabaseOperations): name = 'oracle' oracle = True diff --git a/django/contrib/gis/db/backends/postgis/operations.py b/django/contrib/gis/db/backends/postgis/operations.py index 26a31b3d44..4958aee315 100644 --- a/django/contrib/gis/db/backends/postgis/operations.py +++ b/django/contrib/gis/db/backends/postgis/operations.py @@ -43,7 +43,7 @@ class PostGISDistanceOperator(PostGISOperator): return super(PostGISDistanceOperator, self).as_sql(connection, lookup, template_params, sql_params) -class PostGISOperations(DatabaseOperations, BaseSpatialOperations): +class PostGISOperations(BaseSpatialOperations, DatabaseOperations): name = 'postgis' postgis = True geography = True @@ -179,14 +179,6 @@ class PostGISOperations(DatabaseOperations, BaseSpatialOperations): version = vtup[1:] return version - def check_aggregate_support(self, aggregate): - """ - Checks if the given aggregate name is supported (that is, if it's - in `self.valid_aggregates`). - """ - agg_name = aggregate.__class__.__name__ - return agg_name in self.valid_aggregates - def convert_extent(self, box, srid): """ Returns a 4-tuple extent for the `Extent` aggregate by converting diff --git a/django/contrib/gis/db/backends/spatialite/operations.py b/django/contrib/gis/db/backends/spatialite/operations.py index 8940653930..0d774c9a6d 100644 --- a/django/contrib/gis/db/backends/spatialite/operations.py +++ b/django/contrib/gis/db/backends/spatialite/operations.py @@ -13,7 +13,7 @@ from django.utils import six from django.utils.functional import cached_property -class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations): +class SpatiaLiteOperations(BaseSpatialOperations, DatabaseOperations): name = 'spatialite' spatialite = True version_regex = re.compile(r'^(?P\d)\.(?P\d)\.(?P\d+)') @@ -121,15 +121,6 @@ class SpatiaLiteOperations(DatabaseOperations, BaseSpatialOperations): def geojson(self): return 'AsGeoJSON' if self.spatial_version >= (3, 0, 0) else None - def check_aggregate_support(self, aggregate): - """ - Checks if the given aggregate name is supported (that is, if it's - in `self.valid_aggregates`). - """ - super(SpatiaLiteOperations, self).check_aggregate_support(aggregate) - agg_name = aggregate.__class__.__name__ - return agg_name in self.valid_aggregates - def convert_extent(self, box, srid): """ Convert the polygon data received from Spatialite to min/max values. diff --git a/django/contrib/gis/db/models/aggregates.py b/django/contrib/gis/db/models/aggregates.py index c9476d0f02..b775774c19 100644 --- a/django/contrib/gis/db/models/aggregates.py +++ b/django/contrib/gis/db/models/aggregates.py @@ -7,6 +7,7 @@ __all__ = ['Collect', 'Extent', 'Extent3D', 'MakeLine', 'Union'] class GeoAggregate(Aggregate): template = None function = None + contains_aggregate = 'gis' is_extent = False def as_sql(self, compiler, connection): diff --git a/django/db/backends/base/features.py b/django/db/backends/base/features.py index 0b326bb079..fe13827b77 100644 --- a/django/db/backends/base/features.py +++ b/django/db/backends/base/features.py @@ -224,6 +224,7 @@ class BaseDatabaseFeatures(object): def supports_stddev(self): """Confirm support for STDDEV and related stats functions.""" class StdDevPop(object): + contains_aggregate = True sql_function = 'STDDEV_POP' try: